-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Support spread operator for arrays and tuples in function calls #5296
Comments
Seems like this would also solve #4759. |
@ahejlsberg, you mentioned that you were interested in this proposal. |
This is a pretty basic and useful feature (e.g. for restoring JSON defaults). function test(a: string, b: {}, c: number) {}
test('one', {}, 3); // OK
let params = ['one', {}, 3];
test(...params); // ERROR - as expected
test(...(params as any)); // ERROR - no luck here either :-( |
You can assert the type of the function to (test as any)(...params); |
Ah, right. Thanks @DanielRosenwasser. Hope this gets fixed soon! |
I really like the idea of tuples being matched formal arguments. However currently it is problematic because of the way tuples types. Consider your example: function f(s: string, a: number, b: number, c: number, ...rest: number[]) {
// ...
}
// legal
let quad: [string, number, number, number, number] = ["foo", 1,2,3,4];
f(...quad); // and triple
quad = ["foo", 1, 2, 3, 4, "boo!"]; // it is legal currently
f(...quad); // now it blows up in run time because rest has a string So that issue could be addressed by making tuples more restrictive in assignability (my proposal #6229 sorry) Other thought regarding spreads and tuples:
|
I was surprised when finding that tuple type variables cannot be used with the spread operator in function calls. When the function parameter's types match the tuple's item types I thought this should work. I was convinced that this was working in TypeScript by now (2.1), and struggled to figure out what I was doing wrong. I don't immediately see any progress indication on this issue. |
Based on the discussion in #15747, we would like to pursue this change for arrays, but no special treatment for tuples at the time being. |
* This is due to a bug about spread operator usage fixed on TypeScript 2.4.0 (microsoft/TypeScript#5296) * With this change now a warning will be given about the TS version used. This is expected, you see the discussion about it on angular/angular-cli#7625
Currently, Typescript does not support all uses of Ecmascript's spread operator. Specifically, in function calls, Typescript only supports spreading array arguments that match rest parameters. #4130 is a recent mention of this limitation. I propose two ways of addressing this limitation in function calls:
Although (2) is cleaner from a type checker's point of view, I believe that (1) is more useful because it can type more of the uses that Javascript programmers are accustomed to writing. Of course, both proposals could be implemented.
Proposal 1: Spread operator supports array arguments
The spread operator may be used with the last array argument of a function call, even when that argument doesn't match a rest parameter in the function definition. However, the parameters must all be optional and of the same type. The type must match the element type of the array.
For example,
The checker consumes all parameters that match the array type after the spread operator is used, until
At runtime the spread operator has EcmaScript semantics. Basically,
undefined
if the array is too short, and extra arguments are ignored.Proposal 2: Spread operator supports tuple arguments
The spread operator may be used with a tuple argument at any position in a function call. Extra members of the tuple will even match rest parameters if the tuple is long enough.
The checker matches each member of the spread tuple argument with one parameter until
Notes
The tuple proposal has the problem that it types tuples as tuples in function applications only -- as arrays elsewhere. This is inconsistent, even if function application is arguably the most tuple-like of locations. And it's not clear whether either proposal will allow real uses of the spread operator that Javascript programmers are expecting.
If both proposals are implemented, function calls with spread array literals work in more cases if the literal is always typed as tuple, and provide more and better errors in the cases that do not type check:
So spread array literals should always be interpreted as tuples.
The text was updated successfully, but these errors were encountered: