Spreading an array in a typescript function: Error TS2556

Viewed 8890

I am trying to use the spread-operator on a typescript-function call like this:

function foo(x: number, y: number, z: number) {
  console.log(x + y + z);
}
const args = [0, 1, 2];
foo(...args);

But on compilation, I get the error: "A spread argument must either have a tuple type or be passed to a rest parameter" (TS2556). What am I doing wrong?

Addendum: How can I approach the problem when my argument is a dynamic array, as in

const args = new Array(3).map(() => Math.random());
4 Answers

Edit for dynamically generated args:

Option one: use type assertion if you are sure args will always be 3 elements tuple.

const args = new Array(3).map(() => Math.random()) as [number, number, number];

Option two, define foo to accept rest parameter:

function foo(...args: number[]) {
  console.log(args[0] + args[1] + args[2]);
}
const args = new Array(3).map(() => Math.random());
foo(...args);

Old answer for predefined args

You can assert args as const:

const args = [0, 1, 2] as const;

Playground

Or define args as tuple as the error suggested:

const args: [number, number, number] = [0, 1, 2];

Playground

This is to guarantee that number / type of elements in args always match what's required by the function parameters.

You can use const assertion to get rid of the problem. Because the function foo expects exactly 3 parameters:

function foo(x: number, y: number, z: number) {
  console.log(x + y + z);
}

const args = [0, 1, 2] as const;
foo(...args);

Arguments don’t work in that way, this is how you should you them args

function multiply(n, ...m) {
    return m.map((x) => n * x);
}
// 'a' gets value [10, 20, 30, 40]
const a = multiply(10, 1, 2, 3, 4);

Whoever suffers from A spread argument must either have a tuple type or be passed to a rest parameter., you might want to check whether typescript-parser is install in your devDependencies.

Related