How to get argument types from function in Typescript
How to Get Argument Types from Function in TypeScript
Have you ever found yourself needing to access the types of the parameters in a TypeScript function? You're not alone! It's a common scenario that can be a bit tricky to figure out at first. In this blog post, we'll explore different approaches to get argument types from a function in TypeScript and provide you with easy solutions.
The Problem
Let's start by understanding the problem. Consider the following function:
function test(a: string, b: number) {
console.log(a);
console.log(b);
}
You want to access the types string
and number
of the parameters a
and b
, respectively. However, TypeScript doesn't provide a straightforward way to do this out of the box.
Solution 1: TypeScript's Parameters
Utility Type
One of the simplest solutions is to utilize TypeScript's built-in utility types. The Parameters
utility type allows you to obtain the parameter types from a function. Here's how you can use it:
type TestParams = Parameters<typeof test>;
// Result: [string, number]
// Accessing individual parameter types
type Param1 = TestParams[0]; // string
type Param2 = TestParams[1]; // number
By using Parameters<typeof test>
, you can obtain a tuple type [string, number]
. Then, you can access individual parameter types by indexing the tuple.
Solution 2: Using a Generic Wrapper Function
If you prefer a more explicit approach, you can create a generic wrapper function that captures the argument types. Here's an example:
function getArgumentTypes<T extends (...args: any[]) => any>(fn: T): T {
return fn;
}
const wrappedTest = getArgumentTypes(test);
type WrappedTestParams = Parameters<typeof wrappedTest>;
// Result: [string, number]
// Accessing individual parameter types
type WrappedParam1 = WrappedTestParams[0]; // string
type WrappedParam2 = WrappedTestParams[1]; // number
In this solution, the getArgumentTypes
function takes a function fn
of any type and returns the same function. By wrapping test
with getArgumentTypes
, you can obtain the parameter types just like in the previous solution.
Solution 3: Using a Helper Type
Another approach is to define a helper type that extracts the argument types from a function. Here's an example:
type ArgumentTypes<T> = T extends (...args: infer A) => any ? A : never;
type TestParams = ArgumentTypes<typeof test>;
// Result: [string, number]
// Accessing individual parameter types
type Param1 = TestParams[0]; // string
type Param2 = TestParams[1]; // number
In this solution, we define the ArgumentTypes
helper type that utilizes conditional types and the infer
keyword to extract the argument types from a function. The resulting type TestParams
will be the same as in the previous examples.
Real-Life Scenario: Using Argument Types for Validation
Now that you know how to obtain the argument types from a function in TypeScript, let's consider a real-life scenario where this knowledge can be useful. Suppose you have a function saveUser
that takes a user object and saves it to a database:
interface User {
name: string;
age: number;
email: string;
}
function saveUser(user: User) {
// Save user to the database
}
You can now leverage the argument types to perform type validation on the user object before saving it:
type ValidateUser = (user: User) => void;
const validateUser: ValidateUser = (user) => {
// Perform validation logic
};
const wrappedSaveUser = getArgumentTypes(saveUser);
type SaveUserParams = Parameters<typeof wrappedSaveUser>;
type UserParam = SaveUserParams[0]; // User
validateUser({}); // Type error: Property 'name' is missing in type '{}'
validateUser({ name: "John", age: 25, email: "john@example.com" }); // No type error
By extracting the argument types from saveUser
, you can define a ValidateUser
type that represents the validation function signature. This allows you to create a separate validation function (validateUser
), ensuring that the user object passed to saveUser
is valid before saving it to the database.
Conclusion
Obtaining the argument types from a function in TypeScript is no longer a mysterious challenge. By using TypeScript's built-in utility types, generic wrapper functions, or helper types, you can easily access and utilize the parameter types. Whether you're performing validation, generating documentation, or building more complex solutions, knowing how to get argument types can greatly enhance your TypeScript development experience.
Do you have any other TypeScript questions or challenges? Share them in the comments below! Let's keep exploring and mastering TypeScript together. 🚀