BeetleJuice
BeetleJuice

Reputation: 40896

Why is TypeScript complaining about array length?

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

Answers (1)

jcalz
jcalz

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

Related Questions