Get argument types for function / class constructor

With TypeScript 2.8 you can use the new extends keyword:

type FirstArgument<T> = T extends (arg1: infer U, ...args: any[]) => any ? U : any;
type SecondArgument<T> = T extends (arg1: any, arg2: infer U, ...args: any[]) => any ? U : any;

let arg1: FirstArgument<typeof foo>; // string;
let arg2: SecondArgument<typeof foo>; // number;
let ret: ReturnType<typeof foo>; // string;

I'll throw in a more direct answer for the use case of extracting the constructor argument types.

type GetConstructorArgs<T> = T extends new (...args: infer U) => any ? U : never

class Foo {
    constructor(foo: string, bar: number){
        //
    }
}

type FooConstructorArgs = GetConstructorArgs<typeof Foo> // [string, number]

Typescript now has the ConstructorParameters builtin, similar to the Parameters builtin. Make sure you pass the class type, not the instance:

ConstructorParameters<typeof SomeClass>

ConstructorParameter Official Doc

Parameters Official Doc


Typescript 2.8 added conditional types with type inference

Typescript 3.0 added rest-elements-in-tuple-types, so you can get all the arguments in an Array type now.

type ArgumentsType<T extends (...args: any[]) => any> = T extends (...args: infer A) => any ? A : never;

type Func = (a: number, b: string) => boolean;
type Args = ArgumentsType<Func> // type Args = [number, string];
type Ret = ReturnType<Func> // type Ret = boolean;

You can use it like this:

const func = (...args: Args): Ret => { // type the rest parameters and return type
  const [a, b] = args; // spread the arguments into their names
  console.log(a, b); // use the arguments like normal
  return true;
};

// Above is equivalent to:
const func: Func = (a, b) => {
  console.log(a, b);
  return true;
}

Tags:

Typescript