error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter. is reported for a call like centerOn(...office) when office is an ordinary array. The checker knows it is a number[], an array of any length, so it cannot tell whether it supplies the two arguments centerOn needs.
In JavaScript an array literal is an array of its element type, not a fixed-length tuple. Saying "exactly these two numbers" takes a tuple type in JSDoc, or a const cast.
At a glance
| Code | TS2556 |
|---|---|
| Message | A spread argument must either have a tuple type or be passed to a rest parameter. |
| TypeScript's category | error |
| Listed under | Types do not match |
| Turned on by | No option: every checked file reports it |
| In .js files | Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file |
The message is TypeScript's own text from its diagnostic messages file (Apache-2.0).
What it looks like
/**
* @param {number} lat
* @param {number} lng
*/
export function centerOn(lat, lng) {
return `${lat.toFixed(4)},${lng.toFixed(4)}`;
}
const office = [40.7128, -74.006];
centerOn(...office);error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- The spread value's type is an array type (
number[]) and the function has a fixed list of parameters.
How to fix it
Give the array a tuple type, or cast it to const
/** @type {[number, number]} */ before the declaration makes it a pair; /** @type {const} */ ([41.8781, -87.6298]) makes it a read-only tuple of those exact values. Either one lets the spread fill the parameters.
/**
* @param {number} lat
* @param {number} lng
*/
export function centerOn(lat, lng) {
return `${lat.toFixed(4)},${lng.toFixed(4)}`;
}
/** @type {[number, number]} */
const office = [40.7128, -74.006];
centerOn(...office);
const warehouse = /** @type {const} */ ([41.8781, -87.6298]);
centerOn(...warehouse);
/** @param {...number} values */
export function average(...values) {
return values.reduce((sum, v) => sum + v, 0) / values.length;
}
const scores = [3, 4, 5];
average(...scores);jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Or give the function a rest parameter
If the function works with any number of values, declare it that way: @param {...number} values with ...values in the code. Arrays then spread into it freely.
Gotchas
- Built-ins with rest parameters, such as
Math.max(...values)andconsole.log(...parts), accept any spread array;Math.atan2(...pair)does not. - A
constcast makes the tuplereadonly; passing it to a parameter typed as a mutable array is then an error. That only matters when the function expects an array, not separate arguments.
Sources
- More on Functions: Rest Arguments · TypeScript handbook
- JSDoc Reference: Casts (const) · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.