Search code examples
typescriptparametersarguments

How to use `arguments` where Parameters<...> or similar is expected


Is there a way to use arguments of Some Function where Parameters<Some Function> is expected without asserting etc.?

ex.

function f(a:number, b:number){
    let args:Parameters<typeof f> = arguments // Error: Type 'IArguments' is not assignable to type '[a: number, b: number]'.
}

ex.

function fx(a:number, b:number){
    fy(...arguments); // Error: Type 'IArguments' is not assignable to type '[a: number, b: number]'.
  
}

function fy(a:number, b:number){
    console.log(arguments);
}

Solution

  • This is currently not possible in TypeScript (without something like a type assertion, which you don't want to do).

    Right now the arguments object is given the IArguments type, which is "array-like" in that it has a numeric index signature and a numeric length property, but it's not strongly typed enough to know which argument type is at which numeric index, or the literal type of the length property:

    function f(a: number, b: number) {
        const arg0 = arguments[0];
        // const arg0: any
        const len = arguments.length;
        // const len: number
    }
    

    That is, IArguments is array-like, but it's not tuple-like. There is a longstanding open issue at microsoft/TypeScript#29055 to make arguments more strongly typed, and maybe at some point there'd be a special IArguments<T> type which acts like a tuple type stripped of its array-specific methods (it's a little tricky because currently only actual tuples are considered spreadable into function arguments, so if you try to write a custom IArguments<T> yourself and assign arguments to it, you wouldn't be able to call f(...arguments) without also allowing arguments.map(x => x) which isn't valid).

    For now it's not part of the language, and if you want that behavior you'll need to use type assertions or the like.

    Playground link to code