Is there ArgumentsType<T> like ReturnType<T> in Typescript?

ReturnType<T> extracts return type of a function.

Is there a way to define ArgumentsType<T> that extracts parameter types of a function in tuple format?

For example,

ArgumentsType<(a: number, b: string) => boolean> will be [number, string].

2 answers

  • answered 2018-07-12 07:45 Cerberus

    There is no way for now to extract both the types and amount of arguments for any function possible. But you can try something like this:

    type ArgumentTypes<T> = T extends () => any ? never[] :
                            T extends (a1: infer T1) => any ? [T1] :
                            T extends (a1: infer T1, a2: infer T2) => any ? [T1, T2] :
                            // continue here for any reasonable number of args

    Check it with the following:

    const args0: ArgumentTypes<() => boolean> = []; // correct
    const args1: ArgumentTypes<(a: number) => boolean> = [1]; // correct
    const args2: ArgumentTypes<(a: number, b: string) => boolean> = [1, 'str']; // correct
    const oops0null: ArgumentTypes<() => boolean> = null; // error, arguments are array (but empty one)
    const oops01: ArgumentTypes<() => boolean> = [1]; // error, arguments must be empty
    const oops10: ArgumentTypes<(a: number) => boolean> = []; // error, we need one argument
    const oops12: ArgumentTypes<(a: number) => boolean> = [1, 2]; // error, we need only one argument
    const oops1wrong: ArgumentTypes<(a: number) => boolean> = ['str']; // error, argument must be number
    const oops21: ArgumentTypes<(a: number, b: string) => boolean> = [1]; // error, we need two arguments
    const oops23: ArgumentTypes<(a: number, b: string) => boolean> = [1, 'str', undefined]; // error, we need only two arguments
    const oops2wrong: ArgumentTypes<(a: number, b: string) => boolean> = ['str', 1]; // error, arguments are reversed

    Note that this don't have any use of optional arguments - they are just omitted from the output. I wasn't able to find a way to catch them for now.

  • answered 2018-07-12 07:48 Titian Cernicova-Dragomir

    While this is not possible in the current version of typescript (2.9) without spelling out all parameters. It will become possible in the next version of typescript (3.0) which will be released in the next few days:

    type ArgumentsType<T> = T extends  (...args: infer U) => any ? U: never;
    type argsEmpty = ArgumentsType<() => void> // []
    type args = ArgumentsType<(x: number, y: string, z: boolean) => void> // [number, string, boolean]
    type argsOpt = ArgumentsType<(x: number, y?: string, z?: boolean) => void> // [number, (string | undefined)?, (boolean | undefined)?]

    If you install npm install typescript@next you can already play with this, it should be available sometime this month.


    We can also spread a tuple into arguments with this new feature:

    type Spread<T extends any[]> = (...args: T)=> void;
    type Func = Spread<args> //(x: number, y: string, z: boolean) => void

    You can read more about this feature here