Parameters And Return Type


Problem - Parameters On Github - Return On Github

This time the challenge is to create a copy of the inbuilt Parameters and ReturnType utility types that are provided in Typescript. Thes types accept a function as their generic and return different types based on it.

The Parameters type gives an array of the parameter types that the given function provides. For instance, (one: string, two: boolean) => any will give [string, boolean] as a result.

The ReturnType type gives the return type of the function. For instance, () => boolean will give boolean as a result.

The initial types provided are:

type MyParameters<T extends (...args: any[]) => any> = any
type MyReturnType<T> = any

Solution for Parameters

The given type in this situation is a bit more detailed than the previous questions. The generic type T has been explicitly set to have the shape (...args: any[]) => any which we can use to out advantage. We know that our return type will need to be the actual types from the any[] part.

Below the extends condition has been copied across and added to a ternary where the any[] value passed back.

type MyParameters<T extends (...args: any[]) => any>
    // if the signature is the same, we should change `any[]`
    = T extends (...args: any[]) => any ? any[] : never;

// the Result type equals `any[]` 
type Result = MyParameters<(a: string, b: number) => void>;

This is most of the way there. Now what we need to do if figure out the actual type that the any[] is. This is done in Typescript using the infer keyword. Creating a new Generic type with infer lets Typescript know to pass through the type information of the given parameter.

type MyParameters<T extends (...args: any[]) => any>
    // now infering the `any[]` type
    = T extends (...args: infer U) => any ? U : never;

// the Result type equals `[string, number]` 
type Result = MyParameters<(a: string, b: number) => void>;

Converting to the Returns type

The return type is almost identical to the parameters type - it is only the infer that needs to change its location. Moving infer U to be on the return of the given function rather than the parameters will do what we want.

type MyReturnType<T extends (...args: any[]) => any>
    // now infering the return type
    = T extends (...args: any[]) => infer U ? U : never;

// the Result type equals `boolean` 
type Result = MyReturnType<(a: string, b: number) => boolean>;


What to read more? Check out more posts below!