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
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Operators › Spread_syntax
Spread syntax (...) - JavaScript | MDN
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 ...
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

Adding arbitrary attributes to object using spread operator
It’s not really a bug. If they performed excess property checks with spreading, the resulting errors would be very awkward to work around. Generally, typescript doesn’t care about excess properties. This is why Object.keys emits strings and not keyof T. More on reddit.com
🌐 r/typescript
4
2
April 25, 2024
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
Afraid not. Javascript get syntax does not create a property that is enumerable. It can be accessed directly but won't be accessed via an object spread or a for/in loop. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#using_getters_in_classes More on reddit.com
🌐 r/typescript
22
4
August 8, 2024
Is there a way to set parameters for the "arguments" variable without using the spread operator?
coordinated repeat hobbies reach sense smell snails sophisticated act boat This post was mass deleted and anonymized with Redact More on reddit.com
🌐 r/typescript
11
5
March 20, 2024
🌐
GitBook
basarat.gitbook.io › typescript › future-javascript › spread-operator
Spread Operator | TypeScript Deep Dive
TypeScript Compiler InternalsPowered by GitBook · On this page · Copy · The main objective of the spread operator is to spread the elements of an array or object. This is best explained with examples.
🌐
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, denoted by three dots (`...`), is a powerful tool, that allows you to spread the elements of an array or objects into another array or objects.
🌐
Reddit
reddit.com › r/typescript › adding arbitrary attributes to object using spread operator
r/typescript on Reddit: Adding arbitrary attributes to object using spread operator
April 25, 2024 -

Why is it possible to add arbitrary attributes to an object? This should throw a Typescript error in my opinion.

type Params = {
    limit: number;
}

// Does not work
const params: Params = {
    limit: 20,
    q: "john"
}

// Does work
const spreadParams: Params = {
    limit: 20,
    ...({ q: "john" })
};

console.log(spreadParams.q);
// 'john'

https://www.typescriptlang.org/play/?ssl=18&ssc=10&pln=1&pc=1#code/C4TwDgpgBACghgJzgWwM5QLxQN4CgoFQA2AlsicAFxQB2ArsgEYQIDcuAvrrgPQ9QARAPYR0NIcCgB3IQgDWuAMZCaqSWEQpU1eEjSYc+QqXJUoAJgAMAGiMEAjtQBEAKyEALGk87c+gkegy8koqalCoYAgQcAAmulo6mvpYeITEZBTUVrZpAHT5ABTYUI5Qrh5eUBwAlJzsIapCRBC5REIA5gURUbHxaLn21ex+AORuniO4QA

🌐
TypeScript
typescriptlang.org › docs › handbook › release-notes › typescript-2-1.html
TypeScript: Documentation - TypeScript 2.1
TypeScript 2.1 brings support for ESnext Spread and Rest. Similar to array spread, spreading an object can be handy to get a shallow copy: ... Similarly, you can merge several different objects. In the following example, merged will have properties from foo, bar, and baz. ... The order of specifying spread operations determines what properties end up in the resulting object; properties in later spreads “win out” over previously created properties.
Find elsewhere
🌐
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, ... The spread operator in typescript allows an iterable object like an array or a string to expand in places where 0+ arguments are expected....
🌐
Execute Program
executeprogram.com › courses › everyday-typescript › lessons › object-spread
Everyday TypeScript: Object Spread
Learn programming languages like TypeScript, Python, JavaScript, SQL, and regular expressions. Interactive with real code examples.
🌐
GitHub
github.com › microsoft › TypeScript › issues › 32689
Spread operator for object types and interfaces · Issue #32689 · microsoft/TypeScript
August 2, 2019 - Provide an operator to be used in both {} types and interface types which inherits a set of properties from another object type whilst also allowing for those properties to be selectively overridden.
Published   Aug 02, 2019
🌐
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?
🌐
Jser
jser.dev › shorts › 2023-09-23-spread-not-sound
Spread operator in TypeScript is not sound!!
August 15, 2023 - Before TypeScript improves on this issue, just remember that spread leads to unsound type in TypeScript, it is best to explicit type the variable before spreading.
🌐
Medium
medium.com › @slamflipstrom › conditional-object-properties-using-spread-in-javascript-714e0a12f496
Conditional Object Properties Using Spread in JavaScript | by Sam Lindstrom | Medium
June 6, 2019 - The spread operator ( ... ) allows us to expand iterables into function calls, array literals, and object literals — if you’re using ES2018. Spread syntax allows for some really convenient handling and duplicating of datasets without the ...
🌐
Appsmith
community.appsmith.com › content › guide › javascript-spread-operator-what-are-those-three-dots-my-code
The Javascript Spread Operator - What Are Those Three Dots in My Code? | Appsmith Community Portal
August 29, 2023 - Yes! The spread operator can also be used with other iterable objects like strings, maps, and sets. When used with a string, it spreads each character of the string into individual elements.
🌐
Tim Mousk
timmousk.com › blog › typescript-spread-operator
How To Use The Spread Operator In TypeScript? – Tim Mouskhelichvili
March 27, 2023 - The spread operator allows to spread or expand iterable objects into individual elements.
🌐
DEV Community
dev.to › marinamosti › understanding-the-spread-operator-in-javascript-485j
Understanding the Spread Operator in JavaScript - DEV Community
September 23, 2019 - Good article! However, I feel like it's important to mention that the spread operator does not perform a deep clone on objects, but rather a shallow copy. This means that the spread operator will copy simple values (such as integers, strings and such) but keep the same references for objects.
🌐
Marius Schulz
mariusschulz.com › blog › object-rest-and-spread-in-typescript
Object Rest and Spread in TypeScript — Marius Schulz
July 11, 2019 - Just like Object.assign(), object spread only copies over property values, which might lead to unintended behavior if a value is a reference to another object. Note that none of the code snippets in this post contain any type annotations or other TypeScript-specific constructs.
🌐
TypeScript
typescriptlang.org › docs › handbook › release-notes › typescript-3-0.html
TypeScript: Documentation - TypeScript 3.0
When a function call includes a spread expression of a tuple type as the last argument, the spread expression corresponds to a sequence of discrete arguments of the tuple element types.
🌐
TypeScript
typescriptlang.org › docs › handbook › 2 › functions.html
TypeScript: Documentation - More on Functions
In TypeScript, the type annotation on these parameters is implicitly any[] instead of any, and any type annotation given must be of the form Array<T> or T[], or a tuple type (which we’ll learn about later). Conversely, we can provide a variable number of arguments from an iterable object (for example, an array) using the spread syntax.