Skip to content

Commit 21a5611

Browse files
committed
Merge pull request #2498 from Microsoft/iteratorSpreadDestructure
Support spreading and destructuring of iterators in ES6
2 parents bbd7142 + 846c225 commit 21a5611

File tree

171 files changed

+4298
-72
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

171 files changed

+4298
-72
lines changed

src/compiler/checker.ts

Lines changed: 109 additions & 63 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,8 @@ module ts {
344344
The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: { code: 2485, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant." },
345345
The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant: { code: 2486, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a previously defined constant." },
346346
Invalid_left_hand_side_in_for_of_statement: { code: 2487, category: DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...of' statement." },
347-
The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator: { code: 2488, category: DiagnosticCategory.Error, key: "The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator." },
348-
The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method: { code: 2489, category: DiagnosticCategory.Error, key: "The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method." },
347+
Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator: { code: 2488, category: DiagnosticCategory.Error, key: "Type must have a '[Symbol.iterator]()' method that returns an iterator." },
348+
An_iterator_must_have_a_next_method: { code: 2489, category: DiagnosticCategory.Error, key: "An iterator must have a 'next()' method." },
349349
The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: { code: 2490, category: DiagnosticCategory.Error, key: "The type returned by the 'next()' method of an iterator must have a 'value' property." },
350350
The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: { code: 2491, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern." },
351351
Cannot_redeclare_identifier_0_in_catch_clause: { code: 2492, category: DiagnosticCategory.Error, key: "Cannot redeclare identifier '{0}' in catch clause" },

src/compiler/diagnosticMessages.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,11 +1367,11 @@
13671367
"category": "Error",
13681368
"code": 2487
13691369
},
1370-
"The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator.": {
1370+
"Type must have a '[Symbol.iterator]()' method that returns an iterator.": {
13711371
"category": "Error",
13721372
"code": 2488
13731373
},
1374-
"The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method.": {
1374+
"An iterator must have a 'next()' method.": {
13751375
"category": "Error",
13761376
"code": 2489
13771377
},

src/harness/typeWriter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class TypeWriterWalker {
5252
case ts.SyntaxKind.PostfixUnaryExpression:
5353
case ts.SyntaxKind.BinaryExpression:
5454
case ts.SyntaxKind.ConditionalExpression:
55+
case ts.SyntaxKind.SpreadElementExpression:
5556
this.log(node, this.getTypeOfNode(node));
5657
break;
5758

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,6): error TS2461: Type 'string | number' is not an array type.
2+
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'.
3+
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,14): error TS2322: Type 'string' is not assignable to type 'number'.
24

35

4-
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts (1 errors) ====
6+
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts (3 errors) ====
57
var a: string, b: number;
68
var tuple: [number, string] = [2, "3"];
79
for ([a = 1, b = ""] of tuple) {
810
~~~~~~~~~~~~~~~
911
!!! error TS2461: Type 'string | number' is not an array type.
12+
~
13+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
14+
~
15+
!!! error TS2322: Type 'string' is not assignable to type 'number'.
1016
a;
1117
b;
1218
}

tests/baselines/reference/arrayLiteralSpread.types

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,55 @@ function f0() {
99
var a1 = [...a];
1010
>a1 : number[]
1111
>[...a] : number[]
12+
>...a : number
1213
>a : number[]
1314

1415
var a2 = [1, ...a];
1516
>a2 : number[]
1617
>[1, ...a] : number[]
18+
>...a : number
1719
>a : number[]
1820

1921
var a3 = [1, 2, ...a];
2022
>a3 : number[]
2123
>[1, 2, ...a] : number[]
24+
>...a : number
2225
>a : number[]
2326

2427
var a4 = [...a, 1];
2528
>a4 : number[]
2629
>[...a, 1] : number[]
30+
>...a : number
2731
>a : number[]
2832

2933
var a5 = [...a, 1, 2];
3034
>a5 : number[]
3135
>[...a, 1, 2] : number[]
36+
>...a : number
3237
>a : number[]
3338

3439
var a6 = [1, 2, ...a, 1, 2];
3540
>a6 : number[]
3641
>[1, 2, ...a, 1, 2] : number[]
42+
>...a : number
3743
>a : number[]
3844

3945
var a7 = [1, ...a, 2, ...a];
4046
>a7 : number[]
4147
>[1, ...a, 2, ...a] : number[]
48+
>...a : number
4249
>a : number[]
50+
>...a : number
4351
>a : number[]
4452

4553
var a8 = [...a, ...a, ...a];
4654
>a8 : number[]
4755
>[...a, ...a, ...a] : number[]
56+
>...a : number
4857
>a : number[]
58+
>...a : number
4959
>a : number[]
60+
>...a : number
5061
>a : number[]
5162
}
5263

@@ -60,6 +71,7 @@ function f1() {
6071
var b = ["hello", ...a, true];
6172
>b : (string | number | boolean)[]
6273
>["hello", ...a, true] : (string | number | boolean)[]
74+
>...a : number
6375
>a : number[]
6476

6577
var b: (string | number | boolean)[];
@@ -72,19 +84,29 @@ function f2() {
7284
var a = [...[...[...[...[...[]]]]]];
7385
>a : any[]
7486
>[...[...[...[...[...[]]]]]] : undefined[]
87+
>...[...[...[...[...[]]]]] : undefined
7588
>[...[...[...[...[]]]]] : undefined[]
89+
>...[...[...[...[]]]] : undefined
7690
>[...[...[...[]]]] : undefined[]
91+
>...[...[...[]]] : undefined
7792
>[...[...[]]] : undefined[]
93+
>...[...[]] : undefined
7894
>[...[]] : undefined[]
95+
>...[] : undefined
7996
>[] : undefined[]
8097

8198
var b = [...[...[...[...[...[5]]]]]];
8299
>b : number[]
83100
>[...[...[...[...[...[5]]]]]] : number[]
101+
>...[...[...[...[...[5]]]]] : number
84102
>[...[...[...[...[5]]]]] : number[]
103+
>...[...[...[...[5]]]] : number
85104
>[...[...[...[5]]]] : number[]
105+
>...[...[...[5]]] : number
86106
>[...[...[5]]] : number[]
107+
>...[...[5]] : number
87108
>[...[5]] : number[]
109+
>...[5] : number
88110
>[5] : number[]
89111
}
90112

tests/baselines/reference/callWithSpreadES6.types

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ foo(1, 2, "abc");
3838
foo(1, 2, ...a);
3939
>foo(1, 2, ...a) : void
4040
>foo : (x: number, y: number, ...z: string[]) => void
41+
>...a : string
4142
>a : string[]
4243

4344
foo(1, 2, ...a, "abc");
4445
>foo(1, 2, ...a, "abc") : void
4546
>foo : (x: number, y: number, ...z: string[]) => void
47+
>...a : string
4648
>a : string[]
4749

4850
obj.foo(1, 2, "abc");
@@ -56,13 +58,15 @@ obj.foo(1, 2, ...a);
5658
>obj.foo : (x: number, y: number, ...z: string[]) => any
5759
>obj : X
5860
>foo : (x: number, y: number, ...z: string[]) => any
61+
>...a : string
5962
>a : string[]
6063

6164
obj.foo(1, 2, ...a, "abc");
6265
>obj.foo(1, 2, ...a, "abc") : any
6366
>obj.foo : (x: number, y: number, ...z: string[]) => any
6467
>obj : X
6568
>foo : (x: number, y: number, ...z: string[]) => any
69+
>...a : string
6670
>a : string[]
6771

6872
(obj.foo)(1, 2, "abc");
@@ -78,6 +82,7 @@ obj.foo(1, 2, ...a, "abc");
7882
>obj.foo : (x: number, y: number, ...z: string[]) => any
7983
>obj : X
8084
>foo : (x: number, y: number, ...z: string[]) => any
85+
>...a : string
8186
>a : string[]
8287

8388
(obj.foo)(1, 2, ...a, "abc");
@@ -86,6 +91,7 @@ obj.foo(1, 2, ...a, "abc");
8691
>obj.foo : (x: number, y: number, ...z: string[]) => any
8792
>obj : X
8893
>foo : (x: number, y: number, ...z: string[]) => any
94+
>...a : string
8995
>a : string[]
9096

9197
xa[1].foo(1, 2, "abc");
@@ -101,6 +107,7 @@ xa[1].foo(1, 2, ...a);
101107
>xa[1] : X
102108
>xa : X[]
103109
>foo : (x: number, y: number, ...z: string[]) => any
110+
>...a : string
104111
>a : string[]
105112

106113
xa[1].foo(1, 2, ...a, "abc");
@@ -109,6 +116,7 @@ xa[1].foo(1, 2, ...a, "abc");
109116
>xa[1] : X
110117
>xa : X[]
111118
>foo : (x: number, y: number, ...z: string[]) => any
119+
>...a : string
112120
>a : string[]
113121

114122
(<Function>xa[1].foo)(...[1, 2, "abc"]);
@@ -120,6 +128,7 @@ xa[1].foo(1, 2, ...a, "abc");
120128
>xa[1] : X
121129
>xa : X[]
122130
>foo : (x: number, y: number, ...z: string[]) => any
131+
>...[1, 2, "abc"] : string | number
123132
>[1, 2, "abc"] : (string | number)[]
124133

125134
class C {
@@ -145,6 +154,7 @@ class C {
145154
>foo : (x: number, y: number, ...z: string[]) => void
146155
>x : number
147156
>y : number
157+
>...z : string
148158
>z : string[]
149159
}
150160
foo(x: number, y: number, ...z: string[]) {
@@ -167,6 +177,7 @@ class D extends C {
167177
super(1, 2, ...a);
168178
>super(1, 2, ...a) : void
169179
>super : typeof C
180+
>...a : string
170181
>a : string[]
171182
}
172183
foo() {
@@ -183,6 +194,7 @@ class D extends C {
183194
>super.foo : (x: number, y: number, ...z: string[]) => void
184195
>super : C
185196
>foo : (x: number, y: number, ...z: string[]) => void
197+
>...a : string
186198
>a : string[]
187199
}
188200
}
@@ -192,5 +204,6 @@ var c = new C(1, 2, ...a);
192204
>c : C
193205
>new C(1, 2, ...a) : C
194206
>C : typeof C
207+
>...a : string
195208
>a : string[]
196209

tests/baselines/reference/for-of14.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
tests/cases/conformance/es6/for-ofStatements/for-of14.ts(2,11): error TS2488: The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator.
1+
tests/cases/conformance/es6/for-ofStatements/for-of14.ts(2,11): error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
22

33

44
==== tests/cases/conformance/es6/for-ofStatements/for-of14.ts (1 errors) ====
55
var v: string;
66
for (v of new StringIterator) { } // Should fail because the iterator is not iterable
77
~~~~~~~~~~~~~~~~~~
8-
!!! error TS2488: The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator.
8+
!!! error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
99

1010
class StringIterator {
1111
next() {

tests/baselines/reference/for-of16.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
tests/cases/conformance/es6/for-ofStatements/for-of16.ts(2,11): error TS2489: The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method.
1+
tests/cases/conformance/es6/for-ofStatements/for-of16.ts(2,11): error TS2489: An iterator must have a 'next()' method.
22

33

44
==== tests/cases/conformance/es6/for-ofStatements/for-of16.ts (1 errors) ====
55
var v: string;
66
for (v of new StringIterator) { } // Should fail
77
~~~~~~~~~~~~~~~~~~
8-
!!! error TS2489: The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method.
8+
!!! error TS2489: An iterator must have a 'next()' method.
99

1010
class StringIterator {
1111
[Symbol.iterator]() {

tests/baselines/reference/for-of57.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [for-of57.ts]
2+
var iter: Iterable<number>;
3+
for (let num of iter) { }
4+
5+
//// [for-of57.js]
6+
var iter;
7+
for (let num of iter) { }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
=== tests/cases/conformance/es6/for-ofStatements/for-of57.ts ===
2+
var iter: Iterable<number>;
3+
>iter : Iterable<number>
4+
>Iterable : Iterable<T>
5+
6+
for (let num of iter) { }
7+
>num : number
8+
>iter : Iterable<number>
9+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [iterableArrayPattern1.ts]
2+
var [a, b] = new SymbolIterator;
3+
class SymbolIterator {
4+
next() {
5+
return {
6+
value: Symbol(),
7+
done: false
8+
};
9+
}
10+
11+
[Symbol.iterator]() {
12+
return this;
13+
}
14+
}
15+
16+
//// [iterableArrayPattern1.js]
17+
var [a, b] = new SymbolIterator;
18+
class SymbolIterator {
19+
next() {
20+
return {
21+
value: Symbol(),
22+
done: false
23+
};
24+
}
25+
[Symbol.iterator]() {
26+
return this;
27+
}
28+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
=== tests/cases/conformance/es6/destructuring/iterableArrayPattern1.ts ===
2+
var [a, b] = new SymbolIterator;
3+
>a : symbol
4+
>b : symbol
5+
>new SymbolIterator : SymbolIterator
6+
>SymbolIterator : typeof SymbolIterator
7+
8+
class SymbolIterator {
9+
>SymbolIterator : SymbolIterator
10+
11+
next() {
12+
>next : () => { value: symbol; done: boolean; }
13+
14+
return {
15+
>{ value: Symbol(), done: false } : { value: symbol; done: boolean; }
16+
17+
value: Symbol(),
18+
>value : symbol
19+
>Symbol() : symbol
20+
>Symbol : SymbolConstructor
21+
22+
done: false
23+
>done : boolean
24+
25+
};
26+
}
27+
28+
[Symbol.iterator]() {
29+
>Symbol.iterator : symbol
30+
>Symbol : SymbolConstructor
31+
>iterator : symbol
32+
33+
return this;
34+
>this : SymbolIterator
35+
}
36+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts(2,5): error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.
2+
Property '0' is missing in type 'FooIterator'.
3+
4+
5+
==== tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts (1 errors) ====
6+
function fun([a, b]) { }
7+
fun(new FooIterator);
8+
~~~~~~~~~~~~~~~
9+
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.
10+
!!! error TS2345: Property '0' is missing in type 'FooIterator'.
11+
class Bar { x }
12+
class Foo extends Bar { y }
13+
class FooIterator {
14+
next() {
15+
return {
16+
value: new Foo,
17+
done: false
18+
};
19+
}
20+
21+
[Symbol.iterator]() {
22+
return this;
23+
}
24+
}

0 commit comments

Comments
 (0)