Support assignment patterns in 'for...of' statements
This commit is contained in:
parent
9faa09b5d7
commit
f8150d3734
|
@ -7411,7 +7411,7 @@ module ts {
|
|||
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 {
|
||||
var offendingSymbolOperand =
|
||||
someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left :
|
||||
|
@ -8758,7 +8758,7 @@ module ts {
|
|||
grammarErrorOnFirstToken(node, Diagnostics.for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
checkGrammarForInOrForOfStatement(node)
|
||||
|
||||
// Check the LHS and RHS
|
||||
|
@ -8769,17 +8769,27 @@ module ts {
|
|||
}
|
||||
else {
|
||||
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 iteratedType = getIteratedType(rightType, node.expression);
|
||||
|
||||
// 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
|
||||
// because we accessed properties from anyType, or it may have led to an error inside
|
||||
// getIteratedType.
|
||||
if (iteratedType) {
|
||||
checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
|
||||
// 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
|
||||
// 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
|
||||
// getIteratedType.
|
||||
if (iteratedType) {
|
||||
checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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