Skip to content

Commit 6b71882

Browse files
authored
Fixed spreading iterables into arguments list directly into rest-only signatures (#52838)
1 parent 7bee9c5 commit 6b71882

7 files changed

+413
-3
lines changed

src/compiler/checker.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -32223,19 +32223,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3222332223
}
3222432224

3222532225
function getSpreadArgumentType(args: readonly Expression[], index: number, argCount: number, restType: Type, context: InferenceContext | undefined, checkMode: CheckMode) {
32226+
const inConstContext = isConstTypeVariable(restType);
32227+
3222632228
if (index >= argCount - 1) {
3222732229
const arg = args[argCount - 1];
3222832230
if (isSpreadArgument(arg)) {
3222932231
// We are inferring from a spread expression in the last argument position, i.e. both the parameter
3223032232
// and the argument are ...x forms.
32231-
return getMutableArrayOrTupleType(arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type :
32232-
checkExpressionWithContextualType((arg as SpreadElement).expression, restType, context, checkMode));
32233+
const spreadType = arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type :
32234+
checkExpressionWithContextualType((arg as SpreadElement).expression, restType, context, checkMode);
32235+
32236+
if (isArrayLikeType(spreadType)) {
32237+
return getMutableArrayOrTupleType(spreadType);
32238+
}
32239+
32240+
return createArrayType(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, arg.kind === SyntaxKind.SpreadElement ? (arg as SpreadElement).expression : arg), inConstContext);
3223332241
}
3223432242
}
3223532243
const types = [];
3223632244
const flags = [];
3223732245
const names = [];
32238-
const inConstContext = isConstTypeVariable(restType);
3223932246
for (let i = index; i < argCount; i++) {
3224032247
const arg = args[i];
3224132248
if (isSpreadArgument(arg)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
tests/cases/compiler/argumentsSpreadRestIterables.tsx(1,22): error TS2304: Cannot find name 'Iterable'.
2+
tests/cases/compiler/argumentsSpreadRestIterables.tsx(8,21): error TS2461: Type '"hello"' is not an array type.
3+
tests/cases/compiler/argumentsSpreadRestIterables.tsx(10,27): error TS2461: Type '"hello"' is not an array type.
4+
tests/cases/compiler/argumentsSpreadRestIterables.tsx(15,19): error TS2461: Type '"hello"' is not an array type.
5+
tests/cases/compiler/argumentsSpreadRestIterables.tsx(17,25): error TS2461: Type '"hello"' is not an array type.
6+
7+
8+
==== tests/cases/compiler/argumentsSpreadRestIterables.tsx (5 errors) ====
9+
declare const itNum: Iterable<number>
10+
~~~~~~~~
11+
!!! error TS2304: Cannot find name 'Iterable'.
12+
13+
;(function(...rest) {})(...itNum)
14+
;(function(a, ...rest) {})('', ...itNum)
15+
;(function(a, ...rest) {})('', true, ...itNum)
16+
17+
declare function fn1<const T extends readonly unknown[]>(...args: T): T;
18+
const res1 = fn1(..."hello");
19+
~~~~~~~
20+
!!! error TS2461: Type '"hello"' is not an array type.
21+
const res2 = fn1(...itNum);
22+
const res3 = fn1(true, ..."hello");
23+
~~~~~~~
24+
!!! error TS2461: Type '"hello"' is not an array type.
25+
const res4 = fn1(true, ...itNum);
26+
27+
// repro from #52781
28+
declare function foo<T extends unknown[]>(...args: T): T;
29+
const p1 = foo(..."hello");
30+
~~~~~~~
31+
!!! error TS2461: Type '"hello"' is not an array type.
32+
const p2 = foo(...itNum);
33+
const p3 = foo(true, ..."hello");
34+
~~~~~~~
35+
!!! error TS2461: Type '"hello"' is not an array type.
36+
const p4 = foo(true, ...itNum);
37+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
=== tests/cases/compiler/argumentsSpreadRestIterables.tsx ===
2+
declare const itNum: Iterable<number>
3+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
4+
>Iterable : Symbol(Iterable)
5+
6+
;(function(...rest) {})(...itNum)
7+
>rest : Symbol(rest, Decl(argumentsSpreadRestIterables.tsx, 2, 11))
8+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
9+
10+
;(function(a, ...rest) {})('', ...itNum)
11+
>a : Symbol(a, Decl(argumentsSpreadRestIterables.tsx, 3, 11))
12+
>rest : Symbol(rest, Decl(argumentsSpreadRestIterables.tsx, 3, 13))
13+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
14+
15+
;(function(a, ...rest) {})('', true, ...itNum)
16+
>a : Symbol(a, Decl(argumentsSpreadRestIterables.tsx, 4, 11))
17+
>rest : Symbol(rest, Decl(argumentsSpreadRestIterables.tsx, 4, 13))
18+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
19+
20+
declare function fn1<const T extends readonly unknown[]>(...args: T): T;
21+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
22+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 6, 21))
23+
>args : Symbol(args, Decl(argumentsSpreadRestIterables.tsx, 6, 57))
24+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 6, 21))
25+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 6, 21))
26+
27+
const res1 = fn1(..."hello");
28+
>res1 : Symbol(res1, Decl(argumentsSpreadRestIterables.tsx, 7, 5))
29+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
30+
31+
const res2 = fn1(...itNum);
32+
>res2 : Symbol(res2, Decl(argumentsSpreadRestIterables.tsx, 8, 5))
33+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
34+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
35+
36+
const res3 = fn1(true, ..."hello");
37+
>res3 : Symbol(res3, Decl(argumentsSpreadRestIterables.tsx, 9, 5))
38+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
39+
40+
const res4 = fn1(true, ...itNum);
41+
>res4 : Symbol(res4, Decl(argumentsSpreadRestIterables.tsx, 10, 5))
42+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
43+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
44+
45+
// repro from #52781
46+
declare function foo<T extends unknown[]>(...args: T): T;
47+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
48+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 13, 21))
49+
>args : Symbol(args, Decl(argumentsSpreadRestIterables.tsx, 13, 42))
50+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 13, 21))
51+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 13, 21))
52+
53+
const p1 = foo(..."hello");
54+
>p1 : Symbol(p1, Decl(argumentsSpreadRestIterables.tsx, 14, 5))
55+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
56+
57+
const p2 = foo(...itNum);
58+
>p2 : Symbol(p2, Decl(argumentsSpreadRestIterables.tsx, 15, 5))
59+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
60+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
61+
62+
const p3 = foo(true, ..."hello");
63+
>p3 : Symbol(p3, Decl(argumentsSpreadRestIterables.tsx, 16, 5))
64+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
65+
66+
const p4 = foo(true, ...itNum);
67+
>p4 : Symbol(p4, Decl(argumentsSpreadRestIterables.tsx, 17, 5))
68+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
69+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
70+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
=== tests/cases/compiler/argumentsSpreadRestIterables.tsx ===
2+
declare const itNum: Iterable<number>
3+
>itNum : Iterable<number>
4+
5+
;(function(...rest) {})(...itNum)
6+
>(function(...rest) {})(...itNum) : void
7+
>(function(...rest) {}) : (...rest: Iterable<number>) => void
8+
>function(...rest) {} : (...rest: Iterable<number>) => void
9+
>rest : Iterable<number>
10+
>...itNum : Iterable<number>
11+
>itNum : Iterable<number>
12+
13+
;(function(a, ...rest) {})('', ...itNum)
14+
>(function(a, ...rest) {})('', ...itNum) : void
15+
>(function(a, ...rest) {}) : (a: string, ...rest: Iterable<number>) => void
16+
>function(a, ...rest) {} : (a: string, ...rest: Iterable<number>) => void
17+
>a : string
18+
>rest : Iterable<number>
19+
>'' : ""
20+
>...itNum : Iterable<number>
21+
>itNum : Iterable<number>
22+
23+
;(function(a, ...rest) {})('', true, ...itNum)
24+
>(function(a, ...rest) {})('', true, ...itNum) : void
25+
>(function(a, ...rest) {}) : (a: string, rest_0: boolean, ...rest_1: any[]) => void
26+
>function(a, ...rest) {} : (a: string, rest_0: boolean, ...rest_1: any[]) => void
27+
>a : string
28+
>rest : [boolean, ...any[]]
29+
>'' : ""
30+
>true : true
31+
>...itNum : Iterable<number>
32+
>itNum : Iterable<number>
33+
34+
declare function fn1<const T extends readonly unknown[]>(...args: T): T;
35+
>fn1 : <const T extends readonly unknown[]>(...args: T) => T
36+
>args : T
37+
38+
const res1 = fn1(..."hello");
39+
>res1 : readonly any[]
40+
>fn1(..."hello") : readonly any[]
41+
>fn1 : <const T extends readonly unknown[]>(...args: T) => T
42+
>..."hello" : any
43+
>"hello" : "hello"
44+
45+
const res2 = fn1(...itNum);
46+
>res2 : Iterable<number>
47+
>fn1(...itNum) : Iterable<number>
48+
>fn1 : <const T extends readonly unknown[]>(...args: T) => T
49+
>...itNum : Iterable<number>
50+
>itNum : Iterable<number>
51+
52+
const res3 = fn1(true, ..."hello");
53+
>res3 : readonly [true, ...any[]]
54+
>fn1(true, ..."hello") : readonly [true, ...any[]]
55+
>fn1 : <const T extends readonly unknown[]>(...args: T) => T
56+
>true : true
57+
>..."hello" : any
58+
>"hello" : "hello"
59+
60+
const res4 = fn1(true, ...itNum);
61+
>res4 : readonly [true, ...any[]]
62+
>fn1(true, ...itNum) : readonly [true, ...any[]]
63+
>fn1 : <const T extends readonly unknown[]>(...args: T) => T
64+
>true : true
65+
>...itNum : Iterable<number>
66+
>itNum : Iterable<number>
67+
68+
// repro from #52781
69+
declare function foo<T extends unknown[]>(...args: T): T;
70+
>foo : <T extends unknown[]>(...args: T) => T
71+
>args : T
72+
73+
const p1 = foo(..."hello");
74+
>p1 : any[]
75+
>foo(..."hello") : any[]
76+
>foo : <T extends unknown[]>(...args: T) => T
77+
>..."hello" : any
78+
>"hello" : "hello"
79+
80+
const p2 = foo(...itNum);
81+
>p2 : Iterable<number>
82+
>foo(...itNum) : Iterable<number>
83+
>foo : <T extends unknown[]>(...args: T) => T
84+
>...itNum : Iterable<number>
85+
>itNum : Iterable<number>
86+
87+
const p3 = foo(true, ..."hello");
88+
>p3 : [boolean, ...any[]]
89+
>foo(true, ..."hello") : [boolean, ...any[]]
90+
>foo : <T extends unknown[]>(...args: T) => T
91+
>true : true
92+
>..."hello" : any
93+
>"hello" : "hello"
94+
95+
const p4 = foo(true, ...itNum);
96+
>p4 : [boolean, ...any[]]
97+
>foo(true, ...itNum) : [boolean, ...any[]]
98+
>foo : <T extends unknown[]>(...args: T) => T
99+
>true : true
100+
>...itNum : Iterable<number>
101+
>itNum : Iterable<number>
102+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
=== tests/cases/compiler/argumentsSpreadRestIterables.tsx ===
2+
declare const itNum: Iterable<number>
3+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
4+
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
5+
6+
;(function(...rest) {})(...itNum)
7+
>rest : Symbol(rest, Decl(argumentsSpreadRestIterables.tsx, 2, 11))
8+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
9+
10+
;(function(a, ...rest) {})('', ...itNum)
11+
>a : Symbol(a, Decl(argumentsSpreadRestIterables.tsx, 3, 11))
12+
>rest : Symbol(rest, Decl(argumentsSpreadRestIterables.tsx, 3, 13))
13+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
14+
15+
;(function(a, ...rest) {})('', true, ...itNum)
16+
>a : Symbol(a, Decl(argumentsSpreadRestIterables.tsx, 4, 11))
17+
>rest : Symbol(rest, Decl(argumentsSpreadRestIterables.tsx, 4, 13))
18+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
19+
20+
declare function fn1<const T extends readonly unknown[]>(...args: T): T;
21+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
22+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 6, 21))
23+
>args : Symbol(args, Decl(argumentsSpreadRestIterables.tsx, 6, 57))
24+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 6, 21))
25+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 6, 21))
26+
27+
const res1 = fn1(..."hello");
28+
>res1 : Symbol(res1, Decl(argumentsSpreadRestIterables.tsx, 7, 5))
29+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
30+
31+
const res2 = fn1(...itNum);
32+
>res2 : Symbol(res2, Decl(argumentsSpreadRestIterables.tsx, 8, 5))
33+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
34+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
35+
36+
const res3 = fn1(true, ..."hello");
37+
>res3 : Symbol(res3, Decl(argumentsSpreadRestIterables.tsx, 9, 5))
38+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
39+
40+
const res4 = fn1(true, ...itNum);
41+
>res4 : Symbol(res4, Decl(argumentsSpreadRestIterables.tsx, 10, 5))
42+
>fn1 : Symbol(fn1, Decl(argumentsSpreadRestIterables.tsx, 4, 46))
43+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
44+
45+
// repro from #52781
46+
declare function foo<T extends unknown[]>(...args: T): T;
47+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
48+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 13, 21))
49+
>args : Symbol(args, Decl(argumentsSpreadRestIterables.tsx, 13, 42))
50+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 13, 21))
51+
>T : Symbol(T, Decl(argumentsSpreadRestIterables.tsx, 13, 21))
52+
53+
const p1 = foo(..."hello");
54+
>p1 : Symbol(p1, Decl(argumentsSpreadRestIterables.tsx, 14, 5))
55+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
56+
57+
const p2 = foo(...itNum);
58+
>p2 : Symbol(p2, Decl(argumentsSpreadRestIterables.tsx, 15, 5))
59+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
60+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
61+
62+
const p3 = foo(true, ..."hello");
63+
>p3 : Symbol(p3, Decl(argumentsSpreadRestIterables.tsx, 16, 5))
64+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
65+
66+
const p4 = foo(true, ...itNum);
67+
>p4 : Symbol(p4, Decl(argumentsSpreadRestIterables.tsx, 17, 5))
68+
>foo : Symbol(foo, Decl(argumentsSpreadRestIterables.tsx, 10, 33))
69+
>itNum : Symbol(itNum, Decl(argumentsSpreadRestIterables.tsx, 0, 13))
70+

0 commit comments

Comments
 (0)