Support assignment patterns in 'for...of' statements
This commit is contained in:
parent
9faa09b5d7
commit
f8150d3734
10 changed files with 146 additions and 10 deletions
|
@ -7411,7 +7411,7 @@ module ts {
|
||||||
return rightType;
|
return rightType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return type is true if there was no error, false if there was an error.
|
// Return true if there was no error, false if there was an error.
|
||||||
function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean {
|
function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean {
|
||||||
var offendingSymbolOperand =
|
var offendingSymbolOperand =
|
||||||
someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left :
|
someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left :
|
||||||
|
@ -8769,11 +8769,20 @@ module ts {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var varExpr = <Expression>node.initializer;
|
var varExpr = <Expression>node.initializer;
|
||||||
var leftType = checkExpression(varExpr);
|
|
||||||
checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant);
|
|
||||||
var rightType = checkExpression(node.expression);
|
var rightType = checkExpression(node.expression);
|
||||||
var iteratedType = getIteratedType(rightType, node.expression);
|
var iteratedType = getIteratedType(rightType, node.expression);
|
||||||
|
|
||||||
|
// There may be a destructuring assignment on the left side
|
||||||
|
if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||||
|
// iteratedType may be undefined. In this case, we still want to check the structure of
|
||||||
|
// varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like
|
||||||
|
// to short circuit the type relation checking as much as possible, so we pass the unknownType.
|
||||||
|
checkDestructuringAssignment(varExpr, iteratedType || unknownType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var leftType = checkExpression(varExpr);
|
||||||
|
checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant);
|
||||||
|
|
||||||
// iteratedType will be undefined if the rightType was missing properties/signatures
|
// iteratedType will be undefined if the rightType was missing properties/signatures
|
||||||
// required to get it's iteratedType (like [Symbol.iterator] or next). This may be
|
// required to get it's iteratedType (like [Symbol.iterator] or next). This may be
|
||||||
// because we accessed properties from anyType, or it may have led to an error inside
|
// because we accessed properties from anyType, or it may have led to an error inside
|
||||||
|
@ -8782,6 +8791,7 @@ module ts {
|
||||||
checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
|
checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkSourceElement(node.statement);
|
checkSourceElement(node.statement);
|
||||||
}
|
}
|
||||||
|
|
15
tests/baselines/reference/for-of45.js
Normal file
15
tests/baselines/reference/for-of45.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//// [for-of45.ts]
|
||||||
|
var k: string, v: boolean;
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
for ([k = "", v = false] of map) {
|
||||||
|
k;
|
||||||
|
v;
|
||||||
|
}
|
||||||
|
|
||||||
|
//// [for-of45.js]
|
||||||
|
var k, v;
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
for ([k = "", v = false] of map) {
|
||||||
|
k;
|
||||||
|
v;
|
||||||
|
}
|
26
tests/baselines/reference/for-of45.types
Normal file
26
tests/baselines/reference/for-of45.types
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
=== tests/cases/conformance/es6/for-ofStatements/for-of45.ts ===
|
||||||
|
var k: string, v: boolean;
|
||||||
|
>k : string
|
||||||
|
>v : boolean
|
||||||
|
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
>map : Map<string, boolean>
|
||||||
|
>new Map([["", true]]) : Map<string, boolean>
|
||||||
|
>Map : MapConstructor
|
||||||
|
>[["", true]] : [string, boolean][]
|
||||||
|
>["", true] : [string, boolean]
|
||||||
|
|
||||||
|
for ([k = "", v = false] of map) {
|
||||||
|
>[k = "", v = false] : (string | boolean)[]
|
||||||
|
>k = "" : string
|
||||||
|
>k : string
|
||||||
|
>v = false : boolean
|
||||||
|
>v : boolean
|
||||||
|
>map : Map<string, boolean>
|
||||||
|
|
||||||
|
k;
|
||||||
|
>k : string
|
||||||
|
|
||||||
|
v;
|
||||||
|
>v : boolean
|
||||||
|
}
|
15
tests/baselines/reference/for-of46.errors.txt
Normal file
15
tests/baselines/reference/for-of46.errors.txt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
tests/cases/conformance/es6/for-ofStatements/for-of46.ts(3,7): error TS2322: Type 'boolean' is not assignable to type 'string'.
|
||||||
|
tests/cases/conformance/es6/for-ofStatements/for-of46.ts(3,18): error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/es6/for-ofStatements/for-of46.ts (2 errors) ====
|
||||||
|
var k: string, v: boolean;
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
for ([k = false, v = ""] of map) {
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'boolean' is not assignable to type 'string'.
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||||
|
k;
|
||||||
|
v;
|
||||||
|
}
|
15
tests/baselines/reference/for-of46.js
Normal file
15
tests/baselines/reference/for-of46.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//// [for-of46.ts]
|
||||||
|
var k: string, v: boolean;
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
for ([k = false, v = ""] of map) {
|
||||||
|
k;
|
||||||
|
v;
|
||||||
|
}
|
||||||
|
|
||||||
|
//// [for-of46.js]
|
||||||
|
var k, v;
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
for ([k = false, v = ""] of map) {
|
||||||
|
k;
|
||||||
|
v;
|
||||||
|
}
|
13
tests/baselines/reference/for-of47.errors.txt
Normal file
13
tests/baselines/reference/for-of47.errors.txt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
tests/cases/conformance/es6/for-ofStatements/for-of47.ts(4,13): error TS2322: Type 'boolean' is not assignable to type 'number'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/es6/for-ofStatements/for-of47.ts (1 errors) ====
|
||||||
|
var x: string, y: number;
|
||||||
|
var array = [{ x: "", y: true }]
|
||||||
|
enum E { x }
|
||||||
|
for ({x, y: y = E.x} of array) {
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'boolean' is not assignable to type 'number'.
|
||||||
|
x;
|
||||||
|
y;
|
||||||
|
}
|
20
tests/baselines/reference/for-of47.js
Normal file
20
tests/baselines/reference/for-of47.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//// [for-of47.ts]
|
||||||
|
var x: string, y: number;
|
||||||
|
var array = [{ x: "", y: true }]
|
||||||
|
enum E { x }
|
||||||
|
for ({x, y: y = E.x} of array) {
|
||||||
|
x;
|
||||||
|
y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//// [for-of47.js]
|
||||||
|
var x, y;
|
||||||
|
var array = [{ x: "", y: true }];
|
||||||
|
var E;
|
||||||
|
(function (E) {
|
||||||
|
E[E["x"] = 0] = "x";
|
||||||
|
})(E || (E = {}));
|
||||||
|
for ({ x, y: y = 0 /* x */ } of array) {
|
||||||
|
x;
|
||||||
|
y;
|
||||||
|
}
|
7
tests/cases/conformance/es6/for-ofStatements/for-of45.ts
Normal file
7
tests/cases/conformance/es6/for-ofStatements/for-of45.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
//@target: ES6
|
||||||
|
var k: string, v: boolean;
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
for ([k = "", v = false] of map) {
|
||||||
|
k;
|
||||||
|
v;
|
||||||
|
}
|
7
tests/cases/conformance/es6/for-ofStatements/for-of46.ts
Normal file
7
tests/cases/conformance/es6/for-ofStatements/for-of46.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
//@target: ES6
|
||||||
|
var k: string, v: boolean;
|
||||||
|
var map = new Map([["", true]]);
|
||||||
|
for ([k = false, v = ""] of map) {
|
||||||
|
k;
|
||||||
|
v;
|
||||||
|
}
|
8
tests/cases/conformance/es6/for-ofStatements/for-of47.ts
Normal file
8
tests/cases/conformance/es6/for-ofStatements/for-of47.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
//@target: ES6
|
||||||
|
var x: string, y: number;
|
||||||
|
var array = [{ x: "", y: true }]
|
||||||
|
enum E { x }
|
||||||
|
for ({x, y: y = E.x} of array) {
|
||||||
|
x;
|
||||||
|
y;
|
||||||
|
}
|
Loading…
Reference in a new issue