Reputation: 40896
I have a method that accepts 2 to 4 arguments:
myMethod(a: string, b: string, c?: any, d?: number);
In a unit test, I try to pass arguments to the method this way:
const args: [string, string, any, number] = ['a', 'b', 'c', 0];
myMethod(...args);
Even though I declared args
to be of a set length, the TypeScript compiler shows this error:
TS2556: Expected 2-4 arguments, but got 0 or more.
Why is this error shown? Is there anything I can do to keep the last line (the function call) as it is?
Upvotes: 2
Views: 1523
Reputation: 328187
Note that this issue no longer occurs in TS3.0+, see Playground link. Previous answer:
This is a known issue, and the short answer for why it happens is that rest/spread support in TypeScript was originally designed for arrays and not tuples.
You can wait for tuples in rest/spread positions to be supported in TypeScript; it's supposedly going to be introduced starting in TypeScript 3.0 which should come out soon.
Until then, your only options are workarounds. You could abandon the spread syntax and pass the arguments one by one:
myMethod(args[0], args[1], args[2], args[3]); // type safe but not generalizable
or assert that your method accepts ...args: any[]
as in:
(myMethod as (...args:any[])=>void)(...args); // no error, not type safe
or ignore the error,
// @ts-ignore
myMethod(...args); // no error, not type safe
EDIT: or use the not-currently-well-typed apply()
method (which, unlike the previous two workarounds, changes the emitted js):
myMethod.apply(this, args); // no error, not type safe
None of those are great, so if waiting for the feature to be implemented is an option you might want to do that. Good luck!
Upvotes: 6