A spread argument must either have a tuple type or be passed to a rest parameter

avatar

Borislav Hadzhiev

Wed Mar 09 20222 min read

banner

Photo by Kevin Laminto

A spread argument must either have a tuple type or be passed to a rest parameter #

The error "A spread argument must either have a tuple type or be passed to a rest parameter" occurs when we use the spread syntax with a function that expects a fixed number of parameters. To solve the error, use a tuple instead of an array or type the function to use a rest parameter.

Here is an example of how the error occurs.

index.ts
function getObj(name: string, age: number) { return { name, age, }; } // ⛔️ Error: A spread argument must either // have a tuple type or be passed to a rest parameter.ts(2556) const result = getObj(...['James', 30]);

The cause of the error is - the getObj function takes 2 parameters - a string and a number and we're calling it with the result of using the spread syntax (...) on an array.

TypeScript is telling us that there is no guarantee that the array will have exactly 2 elements, where the first is a string and the second - a number.

To get around this, you could use a const assertion to pass the array as a tuple.

index.ts
function getObj(name: string, age: number) { return { name, age, }; } const result = getObj(...(['James', 30] as const));

The as const syntax converts the array into a readonly tuple.

index.ts
// 👇️ const tuple: readonly ["James", 30] const tuple = ['James', 30] as const;

Now that we're using a tuple, TypeScript knows that we're unpacking an array with only 2 elements, where the first is a string, and the second - a number.

You can also explicitly type the array as a tuple to achieve the same result.

index.ts
function getObj(name: string, age: number) { return { name, age, }; } // 👇️ declare tuple instead of array const myTuple: [string, number] = ['James', 30]; const result = getObj(...myTuple); console.log(result); // 👉️ {name: 'James', age: 30}

We declared a tuple with 2 elements - a string and a number. This exactly matches the arguments the function expects to take, so we can use the spread syntax (...) in the function call.

An alternative approach is to use rest parameters in the function's definition and change the function to take an indefinite number of parameters.

index.ts
function getArr(...args: string[]) { return args; } const result = getArr(...['James', 'Alice', 'Bob', 'Carl']); console.log(result); // 👉️ ['James', 'Alice', 'Bob', 'Carl']

We used a rest parameter in the function's definition. Rest parameters are used for functions that take an indefinite number of arguments.

You can imagine that the ...args syntax will group the passed in arguments into an array.

index.ts
function getArr(...args: string[]) { console.log(args); // 👉️ ['James', 'Alice', 'Bob', 'Carl'] return args; } const result = getArr(...['James', 'Alice', 'Bob', 'Carl']);

The snippet above uses rest arguments (when invoking the getArr function) - to unpack the array elements into comma-separated parameters in the function call.

And it also uses rest parameters (when defining the function) to group all of the passed in arguments into an array called args.

Use the search field on my Home Page to filter through my more than 1,000 articles.