Skip to content

Commit fd0fd36

Browse files
committed
Disallow destructuring in 'for...in'
1 parent 84a22be commit fd0fd36

17 files changed

Lines changed: 78 additions & 5 deletions

src/compiler/checker.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8806,6 +8806,11 @@ module ts {
88068806
// VarDecl must be a variable declaration without a type annotation that declares a variable of type Any,
88078807
// and Expr must be an expression of type Any, an object type, or a type parameter type.
88088808
if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
8809+
var variable = (<VariableDeclarationList>node.initializer).declarations[0];
8810+
if (variable && isBindingPattern(variable.name)) {
8811+
error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
8812+
}
8813+
88098814
checkForInOrForOfVariableDeclaration(node);
88108815
}
88118816
else {
@@ -8815,7 +8820,10 @@ module ts {
88158820
// and Expr must be an expression of type Any, an object type, or a type parameter type.
88168821
var varExpr = <Expression>node.initializer;
88178822
var leftType = checkExpression(varExpr);
8818-
if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike)) {
8823+
if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
8824+
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
8825+
}
8826+
else if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike)) {
88198827
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
88208828
}
88218829
else {

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ module ts {
332332
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." },
333333
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." },
334334
The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property: { code: 2490, category: DiagnosticCategory.Error, key: "The object returned by the next method of the iterator must have a 'value' property." },
335+
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." },
335336
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
336337
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
337338
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },

src/compiler/diagnosticMessages.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,10 @@
13201320
"category": "Error",
13211321
"code": 2490
13221322
},
1323+
"The left-hand side of a 'for...in' statement cannot be a destructuring pattern.": {
1324+
"category": "Error",
1325+
"code": 2491
1326+
},
13231327

13241328
"Import declaration '{0}' is using private name '{1}'.": {
13251329
"category": "Error",
@@ -1596,7 +1600,7 @@
15961600
"Exported type alias '{0}' has or is using private name '{1}'.": {
15971601
"category": "Error",
15981602
"code": 4081
1599-
},
1603+
},
16001604
"The current host does not support the '{0}' option.": {
16011605
"category": "Error",
16021606
"code": 5001

src/compiler/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ module ts {
665665
}
666666

667667
export function isBindingPattern(node: Node) {
668-
return node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern;
668+
return !!node && (node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern);
669669
}
670670

671671
export function isInAmbientContext(node: Node): boolean {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(1,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
2+
3+
4+
==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts (1 errors) ====
5+
for (var [a, b] in []) {}
6+
~~~~~~
7+
!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//// [for-inStatementsDestructuring.ts]
2+
for (var [a, b] in []) {}
3+
4+
//// [for-inStatementsDestructuring.js]
5+
for (var _a = void 0, a = _a[0], b = _a[1] in []) { }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts(1,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
2+
3+
4+
==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts (1 errors) ====
5+
for (var {a, b} in []) {}
6+
~~~~~~
7+
!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//// [for-inStatementsDestructuring2.ts]
2+
for (var {a, b} in []) {}
3+
4+
//// [for-inStatementsDestructuring2.js]
5+
for (var _a = void 0, a = _a.a, b = _a.b in []) { }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts(2,6): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
2+
3+
4+
==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts (1 errors) ====
5+
var a, b;
6+
for ([a, b] in []) { }
7+
~~~~~~
8+
!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [for-inStatementsDestructuring3.ts]
2+
var a, b;
3+
for ([a, b] in []) { }
4+
5+
//// [for-inStatementsDestructuring3.js]
6+
var a, b;
7+
for ([a, b] in []) { }

0 commit comments

Comments
 (0)