So there is a little clause you may have missed:

Type checking requires spread elements to match up with a rest parameter.

Without Rest Parameter

But you can use a type assertion to go dynamic... and it will convert back to ES5 / ES3 for you:

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

(<any>foo)(...args);

This results in the same apply function call that you'd expect:

function foo(x, y, z) {
    console.log(x, y, z);
}
var args = [0, 1, 2];
foo.apply(void 0, args);

With Rest Parameter

The alternative is that it all works just as you expect if the function accepts a rest parameter.

function foo(...x: number[]) { 
 console.log(JSON.stringify(x));
}
var args:number[] = [0, 1, 2];

foo(...args);
Answer from Fenton on Stack Overflow
🌐
Convex
convex.dev › advanced › advanced concepts › spread operator
Spread Operator | TypeScript Guide by Convex
The spread operator expands an array or object into individual elements. ... Rest parameters collect multiple values into an array. ... Quick rule: Spread scatters values out. Rest gathers values in.
Top answer
1 of 4
86

So there is a little clause you may have missed:

Type checking requires spread elements to match up with a rest parameter.

Without Rest Parameter

But you can use a type assertion to go dynamic... and it will convert back to ES5 / ES3 for you:

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

(<any>foo)(...args);

This results in the same apply function call that you'd expect:

function foo(x, y, z) {
    console.log(x, y, z);
}
var args = [0, 1, 2];
foo.apply(void 0, args);

With Rest Parameter

The alternative is that it all works just as you expect if the function accepts a rest parameter.

function foo(...x: number[]) { 
 console.log(JSON.stringify(x));
}
var args:number[] = [0, 1, 2];

foo(...args);
2 of 4
14

I think @Fenton explains it very well but I would like to add some more documentation and possible solutions.

Solutions:

Function overload. I prefer this solution in this case because it keeps some kind of type safety and avoids ignore and any. The original method and function call does not need to be rewritten at all.

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

foo(...args);

Use @ts-ignore to ignore specific line, TypeScript 2.3

function foo(x: number, y: number, z: number) {
  console.log(x, y, z);
}
var args: number[] = [0, 1, 2];
// @ts-ignore
foo(...args);

Use as any.

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

(foo as any)(...args);

Link with documentation regarding the spread operator:

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

Discussions regarding this:

https://github.com/Microsoft/TypeScript/issues/5296 https://github.com/Microsoft/TypeScript/issues/11780 https://github.com/Microsoft/TypeScript/issues/14981 https://github.com/Microsoft/TypeScript/issues/15375

Discussions

Spread operator for object types and interfaces
Search Terms merge, override, spread, rest, operator, object, interface Suggestion Provide an operator to be used in both {} types and interface types which inherits a set of properties from anothe... More on github.com
🌐 github.com
5
August 2, 2019
Spread operator with array and object
The spread operator only copies enumerable own properties of objects, but typescript copies all properties of the object into the receiving type. So in your example, if t = [1, 2, 3], at runtime c = {'0': 1, '1': 2, '2': 3}, but typescript infers the type of c as containing map and all the other methods on an array object, which happens to be assignable to the array type. Typescript does not distinguish between enumerable and non-enumerable properties, so I'm not sure there's a way for the compiler to catch this. But unit tests would catch this! More on reddit.com
🌐 r/typescript
14
8
April 27, 2022
What does in-place mean?
I agree that this is a completely weird and wrong use of the term. In-place means the original array/object is mutated instead of creating a modified copy. array.sort is in-place, because it updates the existing array. array.map is not in-place, because it leaves the original array untouched and returns a new array. https://en.m.wikipedia.org/wiki/In-place_algorithm More on reddit.com
🌐 r/learnjavascript
8
3
August 6, 2023
Conditionally spreading objects in JavaScript
I wouldn’t do that because future engineers may not get it. I’d in-line a ternary …(isActive ? user : {}) More on reddit.com
🌐 r/javascript
44
152
September 19, 2022
🌐
GeeksforGeeks
geeksforgeeks.org › typescript › how-to-use-spread-operator-in-typescript
How to use Spread Operator in TypeScript ? - GeeksforGeeks
July 23, 2025 - The spread operator in TypeScript simplifies array and object manipulation by enabling easy copying, combining, and property modification.
🌐
GitBook
basarat.gitbook.io › typescript › future-javascript › spread-operator
Spread Operator | TypeScript Deep Dive
December 31, 2019 - For the complete documentation index, see llms.txt. This page is also available as Markdown. ... The main objective of the spread operator is to spread the elements of an array or object.
🌐
HowToDoInJava
howtodoinjava.com › home › typescript › typescript / javascript spread operator
TypeScript / JavaScript Spread Operator (with Examples)
July 3, 2023 - The spread operator is a new addition to the features available in the JavaScript ES6 version. The spread operator is used to expand or spread an iterable or an array in Typescript or Javascript. 1. When to use the Spread Operator?
🌐
Tim Mousk
timmousk.com › blog › typescript-spread-operator
How To Use The Spread Operator In TypeScript? – Tim Mouskhelichvili
March 27, 2023 - As you can see, the spread operator is great when you need to copy an array into a new array, merge two arrays, or copy object properties into a new object. But remember that the spread operator only works well on primitive values because it does a shallow copy. If you want to clone objects, you can use a library like clone-deep to make it work. Here are some other TypeScript tutorials for you to enjoy:
🌐
Upmostly
upmostly.com › home › typescript › simplifying your code with the spread operator
Mastering TypeScript's Spread Operator for Cleaner, More Flexible Code - Upmostly
February 22, 2023 - In the first operation, this means we’re modifying the same object. In the second operation, since we’re actually changing what newUsersObject.adam refers to, nothing happens with the original. You can also use the spread operator to merge two objects/arrays together.
Find elsewhere
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Operators › Spread_syntax
Spread syntax (...) - JavaScript - MDN Web Docs - Mozilla
May 22, 2026 - The spread (...) syntax allows an iterable, such as an array or string, to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected. In an object literal, the spread syntax enumerates the properties of an object and adds the key-value ...
🌐
Medium
medium.com › geekculture › a-caveat-on-javascripts-spread-operator-with-typescript-38ccc2fa000e
A caveat on JavaScript’s spread operator with TypeScript | by Taufan | Geek Culture | Medium
May 27, 2021 - A caveat on JavaScript’s spread operator with TypeScript Let’s kickoff this post with this code snippet. Both call to bodyMassIndex will not throw any warning on TypeScript, even though the …
🌐
GitHub
github.com › microsoft › TypeScript › issues › 32689
Spread operator for object types and interfaces · Issue #32689 · microsoft/TypeScript
August 2, 2019 - type Merge<A, B> = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } & B type SizeProps = { width: number, height: number } type MyProps = Merge< SizeProps, { width: number | string, foo: boolean, } > ... This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.) This feature would agree with the rest of TypeScript's Design Goals.
Author   microsoft
🌐
xjavascript
xjavascript.com › blog › typescript-dot-dot-dot-operator
Understanding the TypeScript Spread Operator (`...`) — xjavascript.com
The spread operator in TypeScript allows an iterable (like an array or an object) to be expanded into individual elements. It essentially "spreads" out the contents of an iterable into a new context.
🌐
Medium
medium.com › @aymenfarhani28 › understanding-arrow-functions-default-parameters-and-spread-operator-in-typescript-0e5872b7ec24
Understanding Arrow Functions, Default Parameters and Spread Operator in TypeScript | by Aymen FARHANI | Medium
February 25, 2025 - If a parameter is explicitly set to null, it won’t use the default value. The Spread Operator (...) allows you to expand or "spread" elements from an iterable (like an array or object) into individual elements.
🌐
Medium
medium.com › @kamlesh90 › three-dots-spread-operator-b33f840b85ae
Three dots (…) Spread operator. The three dots in TypeScript are called… | by Kamlesh Singh | Medium
June 30, 2023 - ... When used outside of a function call or declaration, the three dots (…) are known as the spread operator. It allows you to spread elements from an array or an object into another array, object, or function call.
🌐
xjavascript
xjavascript.com › blog › spread-operator-typescript
Mastering the Spread Operator in TypeScript — xjavascript.com
The spread operator (...) in TypeScript takes an iterable (like an array, string, or object) and expands it into individual elements. When used with an array, it unpacks all the elements of the array.
🌐
Scaler
scaler.com › home › topics › typescript › spread syntax with ts tuples
Spread syntax with TS tuples - Typescript
May 4, 2023 - It is the opposite of rest syntax, ... a string into its characters. The spread operator in typescript allows an iterable object like an array or a string to expand in places where 0+ arguments are expected....
🌐
xjavascript
xjavascript.com › blog › typescript-spread-operator
Mastering the TypeScript Spread Operator — xjavascript.com
When the spread operator is applied to an iterable, it expands the elements of that iterable into individual values.
🌐
Reddit
reddit.com › r/typescript › spread operator with array and object
r/typescript on Reddit: Spread operator with array and object
April 27, 2022 -

Edit: This seems to be an issue since 2016, and apparently, no fix (yet? since 2016) because it seems like just an edge case.

Hi all, I accidentally mistyped [ with { at line 4 in the code below and it passes compiler check. Should this happen and why does it behave like that?

        type Foo = number // just an example
        
        let t: Foo[] = [] // [1,2,3] 
        let c: Foo[] = {...t}
        console.log(c.map(e=>-e))

It took me a few minutes in a sea of code to realise what's wrong. Needless to say, it was quite frustrating, I'm sorry if this is a stupid question.

playground link

here is my tsconfig.json

        {
          "compilerOptions": {
            "target": "es5",
            "lib": [
              "dom",
              "dom.iterable",
🌐
Gitbooks
hamednourhani.gitbooks.io › typescript-book › content › docs › spread-operator.html
Spread Operator · typescript-book - Hamed Nourhani
The main objective of the spread operator is to spread the objects of an array. This is best explained with examples. A common use case is to spread an array into the function arguments.
🌐
Technical Feeder
technicalfeeder.com › 2021 › 07 › spread-operator-three-dots-in-javascript-typescript
TypeScript/JavaScript Spread operator (three dots) | Technical Feeder
October 26, 2022 - The spread operator (three dots) is used to copy an array and expand an array to pass the values to another object or function parameters. It can also be used as rest parameters in a function to indicate that the function can take as many arguments ...