Skip to content

Commit 3331d07

Browse files
Merge pull request #26070 from ajafff/tuple-rest
Infer array rest as tuple if possible
2 parents d2647a1 + 8630396 commit 3331d07

File tree

30 files changed

+453
-406
lines changed

30 files changed

+453
-406
lines changed

src/compiler/checker.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4678,11 +4678,11 @@ namespace ts {
46784678
const elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false, /*allowAsyncIterables*/ false);
46794679
const index = pattern.elements.indexOf(declaration);
46804680
if (declaration.dotDotDotToken) {
4681-
// If the parent is a tuple type, the rest element has an array type with a union of the
4681+
// If the parent is a tuple type, the rest element has a tuple type of the
46824682
// remaining tuple element types. Otherwise, the rest element has an array type with same
46834683
// element type as the parent type.
46844684
type = isTupleType(parentType) ?
4685-
getArrayLiteralType((parentType.typeArguments || emptyArray).slice(index, getTypeReferenceArity(parentType))) :
4685+
sliceTupleType(parentType, index) :
46864686
createArrayType(elementType);
46874687
}
46884688
else {
@@ -8725,6 +8725,20 @@ namespace ts {
87258725
return links.resolvedType;
87268726
}
87278727

8728+
function sliceTupleType(type: TupleTypeReference, index: number) {
8729+
const tuple = type.target;
8730+
if (tuple.hasRestElement) {
8731+
// don't slice off rest element
8732+
index = Math.min(index, getTypeReferenceArity(type) - 1);
8733+
}
8734+
return createTupleType(
8735+
(type.typeArguments || emptyArray).slice(index),
8736+
Math.max(0, tuple.minLength - index),
8737+
tuple.hasRestElement,
8738+
tuple.associatedNames && tuple.associatedNames.slice(index),
8739+
);
8740+
}
8741+
87288742
function getTypeFromOptionalTypeNode(node: OptionalTypeNode): Type {
87298743
const type = getTypeFromTypeNode(node.type);
87308744
return strictNullChecks ? getOptionalType(type) : type;
@@ -21691,7 +21705,7 @@ namespace ts {
2169121705
else {
2169221706
checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
2169321707
const type = isTupleType(sourceType) ?
21694-
getArrayLiteralType((sourceType.typeArguments || emptyArray).slice(elementIndex, getTypeReferenceArity(sourceType))) :
21708+
sliceTupleType(sourceType, elementIndex) :
2169521709
createArrayType(elementType);
2169621710
return checkDestructuringAssignment(restExpression, type, checkMode);
2169721711
}

tests/baselines/reference/declarationEmitDestructuring3.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function bar([x, z, ...w]) { }
88
function foo([x, ...y] = [1, "string", true]) { }
99
>foo : ([x, ...y]?: [number, string, boolean]) => void
1010
>x : number
11-
>y : (string | boolean)[]
11+
>y : [string, boolean]
1212
>[1, "string", true] : [number, string, boolean]
1313
>1 : 1
1414
>"string" : "string"

tests/baselines/reference/declarationEmitDestructuringArrayPattern4.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ var _f = [1, "hello", true], x19 = _f[0], y19 = _f[1], z19 = _f[2], a13 = _f.sli
2222

2323
//// [declarationEmitDestructuringArrayPattern4.d.ts]
2424
declare var a5: number[];
25-
declare var x14: number, a6: number[];
26-
declare var x15: number, y15: number, a7: number[];
27-
declare var x16: number, y16: number, z16: number, a8: any[];
25+
declare var x14: number, a6: [number, number];
26+
declare var x15: number, y15: number, a7: [number];
27+
declare var x16: number, y16: number, z16: number, a8: [];
2828
declare var a9: (string | number | boolean)[];
29-
declare var x17: number, a10: (string | boolean)[];
30-
declare var x18: number, y18: string, a12: boolean[];
31-
declare var x19: number, y19: string, z19: boolean, a13: any[];
29+
declare var x17: number, a10: [string, boolean];
30+
declare var x18: number, y18: string, a12: [boolean];
31+
declare var x19: number, y19: string, z19: boolean, a13: [];

tests/baselines/reference/declarationEmitDestructuringArrayPattern4.types

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var [...a5] = [1, 2, 3];
88

99
var [x14, ...a6] = [1, 2, 3];
1010
>x14 : number
11-
>a6 : number[]
11+
>a6 : [number, number]
1212
>[1, 2, 3] : [number, number, number]
1313
>1 : 1
1414
>2 : 2
@@ -17,7 +17,7 @@ var [x14, ...a6] = [1, 2, 3];
1717
var [x15, y15, ...a7] = [1, 2, 3];
1818
>x15 : number
1919
>y15 : number
20-
>a7 : number[]
20+
>a7 : [number]
2121
>[1, 2, 3] : [number, number, number]
2222
>1 : 1
2323
>2 : 2
@@ -27,7 +27,7 @@ var [x16, y16, z16, ...a8] = [1, 2, 3];
2727
>x16 : number
2828
>y16 : number
2929
>z16 : number
30-
>a8 : any[]
30+
>a8 : []
3131
>[1, 2, 3] : [number, number, number]
3232
>1 : 1
3333
>2 : 2
@@ -42,7 +42,7 @@ var [...a9] = [1, "hello", true];
4242

4343
var [x17, ...a10] = [1, "hello", true];
4444
>x17 : number
45-
>a10 : (string | boolean)[]
45+
>a10 : [string, boolean]
4646
>[1, "hello", true] : [number, string, boolean]
4747
>1 : 1
4848
>"hello" : "hello"
@@ -51,7 +51,7 @@ var [x17, ...a10] = [1, "hello", true];
5151
var [x18, y18, ...a12] = [1, "hello", true];
5252
>x18 : number
5353
>y18 : string
54-
>a12 : boolean[]
54+
>a12 : [boolean]
5555
>[1, "hello", true] : [number, string, boolean]
5656
>1 : 1
5757
>"hello" : "hello"
@@ -61,7 +61,7 @@ var [x19, y19, z19, ...a13] = [1, "hello", true];
6161
>x19 : number
6262
>y19 : string
6363
>z19 : boolean
64-
>a13 : any[]
64+
>a13 : []
6565
>[1, "hello", true] : [number, string, boolean]
6666
>1 : 1
6767
>"hello" : "hello"

tests/baselines/reference/declarationsAndAssignments.errors.txt

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -219,37 +219,39 @@ tests/cases/conformance/es6/destructuring/declarationsAndAssignments.ts(138,9):
219219
var x = ([a, b] = [1, 2]);
220220
}
221221

222-
function f20() {
222+
function f20(v: [number, number, number]) {
223223
var x: number;
224224
var y: number;
225225
var z: number;
226-
var a: number[];
227-
var a3: any[];
228-
var [...a] = [1, 2, 3];
229-
var [x, ...a] = [1, 2, 3];
230-
var [x, y, ...a] = [1, 2, 3];
231-
var [x, y, z, ...a3] = [1, 2, 3];
232-
[...a] = [1, 2, 3];
233-
[x, ...a] = [1, 2, 3];
234-
[x, y, ...a] = [1, 2, 3];
235-
[x, y, z, ...a3] = [1, 2, 3];
236-
}
237-
238-
function f21() {
226+
var a0: [];
227+
var a1: [number];
228+
var a2: [number, number];
229+
var a3: [number, number, number];
230+
var [...a3] = v;
231+
var [x, ...a2] = v;
232+
var [x, y, ...a1] = v;
233+
var [x, y, z, ...a0] = v;
234+
[...a3] = v;
235+
[x, ...a2] = v;
236+
[x, y, ...a1] = v;
237+
[x, y, z, ...a0] = v;
238+
}
239+
240+
function f21(v: [number, string, boolean]) {
239241
var x: number;
240242
var y: string;
241243
var z: boolean;
242-
var a0: (number | string | boolean)[];
243-
var a1: (string | boolean)[];
244-
var a2: boolean[];
245-
var a3: any[];
246-
var [...a0] = [1, "hello", true];
247-
var [x, ...a1] = [1, "hello", true];
248-
var [x, y, ...a2] = [1, "hello", true];
249-
var [x, y, z, ...a3] = [1, "hello", true];
250-
[...a0] = [1, "hello", true];
251-
[x, ...a1] = [1, "hello", true];
252-
[x, y, ...a2] = [1, "hello", true];
253-
[x, y, z, ...a3] = [1, "hello", true];
244+
var a0: [number, string, boolean];
245+
var a1: [string, boolean];
246+
var a2: [boolean];
247+
var a3: [];
248+
var [...a0] = v;
249+
var [x, ...a1] = v;
250+
var [x, y, ...a2] = v;
251+
var [x, y, z, ...a3] = v;
252+
[...a0] = v;
253+
[x, ...a1] = v;
254+
[x, y, ...a2] = v;
255+
[x, y, z, ...a3] = v;
254256
}
255257

tests/baselines/reference/declarationsAndAssignments.js

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -149,38 +149,40 @@ function f19() {
149149
var x = ([a, b] = [1, 2]);
150150
}
151151

152-
function f20() {
152+
function f20(v: [number, number, number]) {
153153
var x: number;
154154
var y: number;
155155
var z: number;
156-
var a: number[];
157-
var a3: any[];
158-
var [...a] = [1, 2, 3];
159-
var [x, ...a] = [1, 2, 3];
160-
var [x, y, ...a] = [1, 2, 3];
161-
var [x, y, z, ...a3] = [1, 2, 3];
162-
[...a] = [1, 2, 3];
163-
[x, ...a] = [1, 2, 3];
164-
[x, y, ...a] = [1, 2, 3];
165-
[x, y, z, ...a3] = [1, 2, 3];
156+
var a0: [];
157+
var a1: [number];
158+
var a2: [number, number];
159+
var a3: [number, number, number];
160+
var [...a3] = v;
161+
var [x, ...a2] = v;
162+
var [x, y, ...a1] = v;
163+
var [x, y, z, ...a0] = v;
164+
[...a3] = v;
165+
[x, ...a2] = v;
166+
[x, y, ...a1] = v;
167+
[x, y, z, ...a0] = v;
166168
}
167169

168-
function f21() {
170+
function f21(v: [number, string, boolean]) {
169171
var x: number;
170172
var y: string;
171173
var z: boolean;
172-
var a0: (number | string | boolean)[];
173-
var a1: (string | boolean)[];
174-
var a2: boolean[];
175-
var a3: any[];
176-
var [...a0] = [1, "hello", true];
177-
var [x, ...a1] = [1, "hello", true];
178-
var [x, y, ...a2] = [1, "hello", true];
179-
var [x, y, z, ...a3] = [1, "hello", true];
180-
[...a0] = [1, "hello", true];
181-
[x, ...a1] = [1, "hello", true];
182-
[x, y, ...a2] = [1, "hello", true];
183-
[x, y, z, ...a3] = [1, "hello", true];
174+
var a0: [number, string, boolean];
175+
var a1: [string, boolean];
176+
var a2: [boolean];
177+
var a3: [];
178+
var [...a0] = v;
179+
var [x, ...a1] = v;
180+
var [x, y, ...a2] = v;
181+
var [x, y, z, ...a3] = v;
182+
[...a0] = v;
183+
[x, ...a1] = v;
184+
[x, y, ...a2] = v;
185+
[x, y, z, ...a3] = v;
184186
}
185187

186188

@@ -320,37 +322,37 @@ function f19() {
320322
_d = [[2, 3]][0], _e = _d === void 0 ? [1, 2] : _d, a = _e[0], b = _e[1];
321323
var x = (_f = [1, 2], a = _f[0], b = _f[1], _f);
322324
}
323-
function f20() {
324-
var _a, _b, _c;
325+
function f20(v) {
325326
var x;
326327
var y;
327328
var z;
328-
var a;
329+
var a0;
330+
var a1;
331+
var a2;
329332
var a3;
330-
var a = [1, 2, 3].slice(0);
331-
var _d = [1, 2, 3], x = _d[0], a = _d.slice(1);
332-
var _e = [1, 2, 3], x = _e[0], y = _e[1], a = _e.slice(2);
333-
var _f = [1, 2, 3], x = _f[0], y = _f[1], z = _f[2], a3 = _f.slice(3);
334-
a = [1, 2, 3].slice(0);
335-
_a = [1, 2, 3], x = _a[0], a = _a.slice(1);
336-
_b = [1, 2, 3], x = _b[0], y = _b[1], a = _b.slice(2);
337-
_c = [1, 2, 3], x = _c[0], y = _c[1], z = _c[2], a3 = _c.slice(3);
333+
var a3 = v.slice(0);
334+
var x = v[0], a2 = v.slice(1);
335+
var x = v[0], y = v[1], a1 = v.slice(2);
336+
var x = v[0], y = v[1], z = v[2], a0 = v.slice(3);
337+
a3 = v.slice(0);
338+
x = v[0], a2 = v.slice(1);
339+
x = v[0], y = v[1], a1 = v.slice(2);
340+
x = v[0], y = v[1], z = v[2], a0 = v.slice(3);
338341
}
339-
function f21() {
340-
var _a, _b, _c;
342+
function f21(v) {
341343
var x;
342344
var y;
343345
var z;
344346
var a0;
345347
var a1;
346348
var a2;
347349
var a3;
348-
var a0 = [1, "hello", true].slice(0);
349-
var _d = [1, "hello", true], x = _d[0], a1 = _d.slice(1);
350-
var _e = [1, "hello", true], x = _e[0], y = _e[1], a2 = _e.slice(2);
351-
var _f = [1, "hello", true], x = _f[0], y = _f[1], z = _f[2], a3 = _f.slice(3);
352-
a0 = [1, "hello", true].slice(0);
353-
_a = [1, "hello", true], x = _a[0], a1 = _a.slice(1);
354-
_b = [1, "hello", true], x = _b[0], y = _b[1], a2 = _b.slice(2);
355-
_c = [1, "hello", true], x = _c[0], y = _c[1], z = _c[2], a3 = _c.slice(3);
350+
var a0 = v.slice(0);
351+
var x = v[0], a1 = v.slice(1);
352+
var x = v[0], y = v[1], a2 = v.slice(2);
353+
var x = v[0], y = v[1], z = v[2], a3 = v.slice(3);
354+
a0 = v.slice(0);
355+
x = v[0], a1 = v.slice(1);
356+
x = v[0], y = v[1], a2 = v.slice(2);
357+
x = v[0], y = v[1], z = v[2], a3 = v.slice(3);
356358
}

0 commit comments

Comments
 (0)