diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3cd42bd6008f3..a85633abf25fa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -41529,10 +41529,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // VarDecl must be a variable declaration without a type annotation that declares a variable of type Any, // and Expr must be an expression of type Any, an object type, or a type parameter type. if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { - const variable = (node.initializer as VariableDeclarationList).declarations[0]; - if (variable && isBindingPattern(variable.name)) { - error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); - } checkVariableDeclarationList(node.initializer as VariableDeclarationList); } else { @@ -41542,8 +41538,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // and Expr must be an expression of type Any, an object type, or a type parameter type. const varExpr = node.initializer; const leftType = checkExpression(varExpr); - if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { - error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); + if (isAssignmentPattern(varExpr)) { + checkDestructuringAssignment(varExpr, getIndexTypeOrString(rightType)); } else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) { error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e15199127169c..e508e3b40b434 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2372,10 +2372,6 @@ "category": "Error", "code": 2490 }, - "The left-hand side of a 'for...in' statement cannot be a destructuring pattern.": { - "category": "Error", - "code": 2491 - }, "Cannot redeclare identifier '{0}' in catch clause.": { "category": "Error", "code": 2492 diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 5e2b895a23498..5518cd4bb643d 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -51,6 +51,7 @@ import { flattenDestructuringAssignment, flattenDestructuringBinding, FlattenLevel, + ForInOrOfStatement, ForInStatement, ForOfStatement, ForStatement, @@ -85,6 +86,7 @@ import { isArrayLiteralExpression, isArrowFunction, isAssignmentExpression, + isAssignmentPattern, isBinaryExpression, isBindingPattern, isBlock, @@ -2684,11 +2686,16 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } function visitForInStatement(node: ForInStatement, outermostLabeledStatement: LabeledStatement | undefined) { + const needsConversionForDestructuring = node.initializer.kind === SyntaxKind.VariableDeclarationList ? + isBindingPattern((node.initializer as VariableDeclarationList).declarations[0].name) : + isAssignmentPattern(node.initializer); return visitIterationStatementWithFacts( HierarchyFacts.ForInOrForOfStatementExcludes, HierarchyFacts.ForInOrForOfStatementIncludes, node, - outermostLabeledStatement); + outermostLabeledStatement, + needsConversionForDestructuring ? convertForInStatementForDestructuring : undefined + ); } function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { @@ -2700,7 +2707,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray); } - function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[] | undefined) { + function convertForInOrOfStatementHead(node: ForInOrOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[] | undefined) { const statements: Statement[] = []; const initializer = node.initializer; if (isVariableDeclarationList(initializer)) { @@ -2800,6 +2807,36 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ); } + function convertForInStatementForDestructuring(node: ForInStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined): Statement { + const lhsReference = factory.createUniqueName("key"); + + const forInStatement = setEmitFlags( + setTextRange( + factory.createForInStatement( + /*initializer*/ setEmitFlags( + setTextRange( + factory.createVariableDeclarationList([ + setTextRange(factory.createVariableDeclaration(lhsReference, /*exclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined), node.initializer), + ]), + node.expression + ), + EmitFlags.NoHoisting + ), + /*expression*/ node.expression, + /*statement*/ convertForInOrOfStatementHead( + node, + lhsReference, + convertedLoopBodyStatements + ) + ), + /*location*/ node + ), + EmitFlags.NoTokenTrailingSourceMaps + ); + + return factory.restoreEnclosingLabel(forInStatement, outermostLabeledStatement, convertedLoopState && resetLabel); + } + function convertForOfStatementForArray(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined): Statement { // The following ES6 code: // @@ -2856,7 +2893,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile node.expression ), /*incrementor*/ setTextRange(factory.createPostfixIncrement(counter), node.expression), - /*statement*/ convertForOfStatementHead( + /*statement*/ convertForInOrOfStatementHead( node, factory.createElementAccessExpression(rhsReference, counter), convertedLoopBodyStatements @@ -2867,7 +2904,6 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. setEmitFlags(forStatement, EmitFlags.NoTokenTrailingSourceMaps); - setTextRange(forStatement, node); return factory.restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel); } @@ -2905,7 +2941,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ), /*condition*/ factory.createLogicalNot(factory.createPropertyAccessExpression(result, "done")), /*incrementor*/ factory.createAssignment(result, next), - /*statement*/ convertForOfStatementHead( + /*statement*/ convertForInOrOfStatementHead( node, factory.createPropertyAccessExpression(result, "value"), convertedLoopBodyStatements diff --git a/src/testRunner/unittests/evaluation/destructuring.ts b/src/testRunner/unittests/evaluation/destructuring.ts index c52c4d4b0a61a..e994ace43c026 100644 --- a/src/testRunner/unittests/evaluation/destructuring.ts +++ b/src/testRunner/unittests/evaluation/destructuring.ts @@ -65,4 +65,36 @@ describe("unittests:: evaluation:: destructuring", () => { assert.deepEqual(result.output, { a: 1, b: { y: 2 } }); }); }); + describe("correct evaluation in for-in with array pattern", () => { + it("ES5", () => { + const result = evaluator.evaluateTypeScript(` + export let output: string; + for (const [first] in { test: 1 }) { output = first; } + `, { target: ts.ScriptTarget.ES5, downlevelIteration: true }); + assert.deepEqual(result.output, "t"); + }); + it("ESNext", () => { + const result = evaluator.evaluateTypeScript(` + export let output: string; + for (const [first] in { test: 1 }) { output = first; } + `, { target: ts.ScriptTarget.ESNext }); + assert.deepEqual(result.output, "t"); + }); + }); + describe("correct evaluation in for-in with object pattern", () => { + it("ES5", () => { + const result = evaluator.evaluateTypeScript(` + export let output: number; + for (const { length } in { test: 1 }) { output = length; } + `, { target: ts.ScriptTarget.ES5, downlevelIteration: true }); + assert.deepEqual(result.output, 4); + }); + it("ESNext", () => { + const result = evaluator.evaluateTypeScript(` + export let output: number; + for (const { length } in { test: 1 }) { output = length; } + `, { target: ts.ScriptTarget.ESNext }); + assert.deepEqual(result.output, 4); + }); + }); }); diff --git a/tests/baselines/reference/for-inStatementsDestructuring.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring.errors.txt index 13ce4a4992840..47635c22e615b 100644 --- a/tests/baselines/reference/for-inStatementsDestructuring.errors.txt +++ b/tests/baselines/reference/for-inStatementsDestructuring.errors.txt @@ -1,10 +1,7 @@ for-inStatementsDestructuring.ts(1,10): error TS2461: Type 'string' is not an array type. -for-inStatementsDestructuring.ts(1,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. -==== for-inStatementsDestructuring.ts (2 errors) ==== +==== for-inStatementsDestructuring.ts (1 errors) ==== for (var [a, b] in []) {} ~~~~~~ -!!! error TS2461: Type 'string' is not an array type. - ~~~~~~ -!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. \ No newline at end of file +!!! error TS2461: Type 'string' is not an array type. \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring.js b/tests/baselines/reference/for-inStatementsDestructuring.js index a2a6744972bbb..546711b35d17a 100644 --- a/tests/baselines/reference/for-inStatementsDestructuring.js +++ b/tests/baselines/reference/for-inStatementsDestructuring.js @@ -4,4 +4,6 @@ for (var [a, b] in []) {} //// [for-inStatementsDestructuring.js] -for (var _a = void 0, a = _a[0], b = _a[1] in []) { } +for (var key_1 in []) { + var a = key_1[0], b = key_1[1]; +} diff --git a/tests/baselines/reference/for-inStatementsDestructuring2.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring2.errors.txt index f707db592b2b2..01b790e5ddc55 100644 --- a/tests/baselines/reference/for-inStatementsDestructuring2.errors.txt +++ b/tests/baselines/reference/for-inStatementsDestructuring2.errors.txt @@ -1,12 +1,9 @@ -for-inStatementsDestructuring2.ts(1,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. for-inStatementsDestructuring2.ts(1,11): error TS2339: Property 'a' does not exist on type 'String'. for-inStatementsDestructuring2.ts(1,14): error TS2339: Property 'b' does not exist on type 'String'. -==== for-inStatementsDestructuring2.ts (3 errors) ==== +==== for-inStatementsDestructuring2.ts (2 errors) ==== for (var {a, b} in []) {} - ~~~~~~ -!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. ~ !!! error TS2339: Property 'a' does not exist on type 'String'. ~ diff --git a/tests/baselines/reference/for-inStatementsDestructuring2.js b/tests/baselines/reference/for-inStatementsDestructuring2.js index 51eb2c751eefe..1964d04720737 100644 --- a/tests/baselines/reference/for-inStatementsDestructuring2.js +++ b/tests/baselines/reference/for-inStatementsDestructuring2.js @@ -4,4 +4,6 @@ for (var {a, b} in []) {} //// [for-inStatementsDestructuring2.js] -for (var _a = void 0, a = _a.a, b = _a.b in []) { } +for (var key_1 in []) { + var a = key_1.a, b = key_1.b; +} diff --git a/tests/baselines/reference/for-inStatementsDestructuring3.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring3.errors.txt index a2604d892c124..5de69a1245288 100644 --- a/tests/baselines/reference/for-inStatementsDestructuring3.errors.txt +++ b/tests/baselines/reference/for-inStatementsDestructuring3.errors.txt @@ -1,8 +1,8 @@ -for-inStatementsDestructuring3.ts(2,6): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. +for-inStatementsDestructuring3.ts(2,6): error TS2461: Type '"length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"' is not an array type. ==== for-inStatementsDestructuring3.ts (1 errors) ==== var a, b; for ([a, b] in []) { } ~~~~~~ -!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. \ No newline at end of file +!!! error TS2461: Type '"length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"' is not an array type. \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring4.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring4.errors.txt index 46fb53162f74e..91d502000d932 100644 --- a/tests/baselines/reference/for-inStatementsDestructuring4.errors.txt +++ b/tests/baselines/reference/for-inStatementsDestructuring4.errors.txt @@ -1,8 +1,11 @@ -for-inStatementsDestructuring4.ts(2,6): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. +for-inStatementsDestructuring4.ts(2,7): error TS2339: Property 'a' does not exist on type '"length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"'. +for-inStatementsDestructuring4.ts(2,10): error TS2339: Property 'b' does not exist on type '"length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"'. -==== for-inStatementsDestructuring4.ts (1 errors) ==== +==== for-inStatementsDestructuring4.ts (2 errors) ==== var a, b; for ({a, b} in []) { } - ~~~~~~ -!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. \ No newline at end of file + ~ +!!! error TS2339: Property 'a' does not exist on type '"length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"'. + ~ +!!! error TS2339: Property 'b' does not exist on type '"length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"'. \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring4.js b/tests/baselines/reference/for-inStatementsDestructuring4.js index 83d6e3cf3d101..c18945e7c1bf3 100644 --- a/tests/baselines/reference/for-inStatementsDestructuring4.js +++ b/tests/baselines/reference/for-inStatementsDestructuring4.js @@ -6,4 +6,6 @@ for ({a, b} in []) { } //// [for-inStatementsDestructuring4.js] var a, b; -for ({ a: a, b: b } in []) { } +for (var key_1 in []) { + a = key_1.a, b = key_1.b; +} diff --git a/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).errors.txt b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).errors.txt new file mode 100644 index 0000000000000..a025320401ee4 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).errors.txt @@ -0,0 +1,11 @@ +for-inStatementsDestructuring5.ts(4,6): error TS2461: Type 'string' is not an array type. + + +==== for-inStatementsDestructuring5.ts (1 errors) ==== + let a: string; + declare let obj: { [s: string]: string }; + + for ([a] in obj) {} + ~~~ +!!! error TS2461: Type 'string' is not an array type. + \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).js b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).js new file mode 100644 index 0000000000000..833fc7711f171 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).js @@ -0,0 +1,12 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts] //// + +//// [for-inStatementsDestructuring5.ts] +let a: string; +declare let obj: { [s: string]: string }; + +for ([a] in obj) {} + + +//// [for-inStatementsDestructuring5.js] +var a; +for ([a] in obj) { } diff --git a/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).symbols b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).symbols new file mode 100644 index 0000000000000..64befc73d4169 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).symbols @@ -0,0 +1,14 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts] //// + +=== for-inStatementsDestructuring5.ts === +let a: string; +>a : Symbol(a, Decl(for-inStatementsDestructuring5.ts, 0, 3)) + +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring5.ts, 1, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring5.ts, 1, 20)) + +for ([a] in obj) {} +>a : Symbol(a, Decl(for-inStatementsDestructuring5.ts, 0, 3)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring5.ts, 1, 11)) + diff --git a/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).types b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).types new file mode 100644 index 0000000000000..46376ffbf9402 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring5(target=es5).types @@ -0,0 +1,15 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts] //// + +=== for-inStatementsDestructuring5.ts === +let a: string; +>a : string + +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for ([a] in obj) {} +>[a] : [string] +>a : string +>obj : { [s: string]: string; } + diff --git a/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).js b/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).js new file mode 100644 index 0000000000000..6379db7d02e99 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).js @@ -0,0 +1,12 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts] //// + +//// [for-inStatementsDestructuring5.ts] +let a: string; +declare let obj: { [s: string]: string }; + +for ([a] in obj) {} + + +//// [for-inStatementsDestructuring5.js] +let a; +for ([a] in obj) { } diff --git a/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).symbols b/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).symbols new file mode 100644 index 0000000000000..64befc73d4169 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).symbols @@ -0,0 +1,14 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts] //// + +=== for-inStatementsDestructuring5.ts === +let a: string; +>a : Symbol(a, Decl(for-inStatementsDestructuring5.ts, 0, 3)) + +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring5.ts, 1, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring5.ts, 1, 20)) + +for ([a] in obj) {} +>a : Symbol(a, Decl(for-inStatementsDestructuring5.ts, 0, 3)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring5.ts, 1, 11)) + diff --git a/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).types b/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).types new file mode 100644 index 0000000000000..46376ffbf9402 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring5(target=esnext).types @@ -0,0 +1,15 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts] //// + +=== for-inStatementsDestructuring5.ts === +let a: string; +>a : string + +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for ([a] in obj) {} +>[a] : [string] +>a : string +>obj : { [s: string]: string; } + diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).errors.txt b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).errors.txt new file mode 100644 index 0000000000000..a59a1c3f00ffa --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).errors.txt @@ -0,0 +1,12 @@ +for-inStatementsDestructuring6.ts(5,6): error TS2461: Type 'string' is not an array type. + + +==== for-inStatementsDestructuring6.ts (1 errors) ==== + let b: number; + let c: string[]; + declare let obj: { [s: string]: string }; + + for ([b, ...c] in obj) {} + ~~~~~~~~~ +!!! error TS2461: Type 'string' is not an array type. + \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).js b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).js new file mode 100644 index 0000000000000..ebd1fc0138342 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).js @@ -0,0 +1,16 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts] //// + +//// [for-inStatementsDestructuring6.ts] +let b: number; +let c: string[]; +declare let obj: { [s: string]: string }; + +for ([b, ...c] in obj) {} + + +//// [for-inStatementsDestructuring6.js] +var b; +var c; +for (var key_1 in obj) { + b = key_1[0], c = key_1.slice(1); +} diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).symbols b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).symbols new file mode 100644 index 0000000000000..37b4d6c1b02b5 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).symbols @@ -0,0 +1,18 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts] //// + +=== for-inStatementsDestructuring6.ts === +let b: number; +>b : Symbol(b, Decl(for-inStatementsDestructuring6.ts, 0, 3)) + +let c: string[]; +>c : Symbol(c, Decl(for-inStatementsDestructuring6.ts, 1, 3)) + +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring6.ts, 2, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring6.ts, 2, 20)) + +for ([b, ...c] in obj) {} +>b : Symbol(b, Decl(for-inStatementsDestructuring6.ts, 0, 3)) +>c : Symbol(c, Decl(for-inStatementsDestructuring6.ts, 1, 3)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring6.ts, 2, 11)) + diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).types b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).types new file mode 100644 index 0000000000000..0bac4a3b5f86f --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=es5).types @@ -0,0 +1,20 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts] //// + +=== for-inStatementsDestructuring6.ts === +let b: number; +>b : number + +let c: string[]; +>c : string[] + +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for ([b, ...c] in obj) {} +>[b, ...c] : [number, ...string[]] +>b : number +>...c : string +>c : string[] +>obj : { [s: string]: string; } + diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).errors.txt b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).errors.txt new file mode 100644 index 0000000000000..94092fdf9617b --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).errors.txt @@ -0,0 +1,12 @@ +for-inStatementsDestructuring6.ts(5,7): error TS2322: Type 'string' is not assignable to type 'number'. + + +==== for-inStatementsDestructuring6.ts (1 errors) ==== + let b: number; + let c: string[]; + declare let obj: { [s: string]: string }; + + for ([b, ...c] in obj) {} + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. + \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).js b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).js new file mode 100644 index 0000000000000..4320326d32ce2 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).js @@ -0,0 +1,14 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts] //// + +//// [for-inStatementsDestructuring6.ts] +let b: number; +let c: string[]; +declare let obj: { [s: string]: string }; + +for ([b, ...c] in obj) {} + + +//// [for-inStatementsDestructuring6.js] +let b; +let c; +for ([b, ...c] in obj) { } diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).symbols b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).symbols new file mode 100644 index 0000000000000..37b4d6c1b02b5 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).symbols @@ -0,0 +1,18 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts] //// + +=== for-inStatementsDestructuring6.ts === +let b: number; +>b : Symbol(b, Decl(for-inStatementsDestructuring6.ts, 0, 3)) + +let c: string[]; +>c : Symbol(c, Decl(for-inStatementsDestructuring6.ts, 1, 3)) + +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring6.ts, 2, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring6.ts, 2, 20)) + +for ([b, ...c] in obj) {} +>b : Symbol(b, Decl(for-inStatementsDestructuring6.ts, 0, 3)) +>c : Symbol(c, Decl(for-inStatementsDestructuring6.ts, 1, 3)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring6.ts, 2, 11)) + diff --git a/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).types b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).types new file mode 100644 index 0000000000000..0bac4a3b5f86f --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring6(target=esnext).types @@ -0,0 +1,20 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts] //// + +=== for-inStatementsDestructuring6.ts === +let b: number; +>b : number + +let c: string[]; +>c : string[] + +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for ([b, ...c] in obj) {} +>[b, ...c] : [number, ...string[]] +>b : number +>...c : string +>c : string[] +>obj : { [s: string]: string; } + diff --git a/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).errors.txt b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).errors.txt new file mode 100644 index 0000000000000..6b4e2d02ca906 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).errors.txt @@ -0,0 +1,13 @@ +for-inStatementsDestructuring7.ts(3,10): error TS2461: Type 'string' is not an array type. + + +==== for-inStatementsDestructuring7.ts (1 errors) ==== + declare let obj: { [s: string]: string }; + + for (let [b, ...c] in obj) { + ~~~~~~~~~ +!!! error TS2461: Type 'string' is not an array type. + b; + c; + } + \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).js b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).js new file mode 100644 index 0000000000000..611daa3040460 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).js @@ -0,0 +1,17 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts] //// + +//// [for-inStatementsDestructuring7.ts] +declare let obj: { [s: string]: string }; + +for (let [b, ...c] in obj) { + b; + c; +} + + +//// [for-inStatementsDestructuring7.js] +for (var key_1 in obj) { + var b = key_1[0], c = key_1.slice(1); + b; + c; +} diff --git a/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).symbols b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).symbols new file mode 100644 index 0000000000000..d6a463e2459a7 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).symbols @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts] //// + +=== for-inStatementsDestructuring7.ts === +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring7.ts, 0, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring7.ts, 0, 20)) + +for (let [b, ...c] in obj) { +>b : Symbol(b, Decl(for-inStatementsDestructuring7.ts, 2, 10)) +>c : Symbol(c, Decl(for-inStatementsDestructuring7.ts, 2, 12)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring7.ts, 0, 11)) + + b; +>b : Symbol(b, Decl(for-inStatementsDestructuring7.ts, 2, 10)) + + c; +>c : Symbol(c, Decl(for-inStatementsDestructuring7.ts, 2, 12)) +} + diff --git a/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).types b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).types new file mode 100644 index 0000000000000..bdb30adf0516c --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring7(target=es5).types @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts] //// + +=== for-inStatementsDestructuring7.ts === +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for (let [b, ...c] in obj) { +>b : any +>c : any[] +>obj : { [s: string]: string; } + + b; +>b : any + + c; +>c : any[] +} + diff --git a/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).js b/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).js new file mode 100644 index 0000000000000..f7254f007a13f --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).js @@ -0,0 +1,16 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts] //// + +//// [for-inStatementsDestructuring7.ts] +declare let obj: { [s: string]: string }; + +for (let [b, ...c] in obj) { + b; + c; +} + + +//// [for-inStatementsDestructuring7.js] +for (let [b, ...c] in obj) { + b; + c; +} diff --git a/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).symbols b/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).symbols new file mode 100644 index 0000000000000..d6a463e2459a7 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).symbols @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts] //// + +=== for-inStatementsDestructuring7.ts === +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring7.ts, 0, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring7.ts, 0, 20)) + +for (let [b, ...c] in obj) { +>b : Symbol(b, Decl(for-inStatementsDestructuring7.ts, 2, 10)) +>c : Symbol(c, Decl(for-inStatementsDestructuring7.ts, 2, 12)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring7.ts, 0, 11)) + + b; +>b : Symbol(b, Decl(for-inStatementsDestructuring7.ts, 2, 10)) + + c; +>c : Symbol(c, Decl(for-inStatementsDestructuring7.ts, 2, 12)) +} + diff --git a/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).types b/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).types new file mode 100644 index 0000000000000..64dd0ed312cbc --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring7(target=esnext).types @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts] //// + +=== for-inStatementsDestructuring7.ts === +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for (let [b, ...c] in obj) { +>b : string +>c : string[] +>obj : { [s: string]: string; } + + b; +>b : string + + c; +>c : string[] +} + diff --git a/tests/baselines/reference/for-inStatementsDestructuring8.js b/tests/baselines/reference/for-inStatementsDestructuring8.js new file mode 100644 index 0000000000000..244fef2064578 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring8.js @@ -0,0 +1,15 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring8.ts] //// + +//// [for-inStatementsDestructuring8.ts] +declare let obj: { [s: string]: string }; + +for (let { length: length1 } in obj) { + length1 +} + + +//// [for-inStatementsDestructuring8.js] +for (var key_1 in obj) { + var length1 = key_1.length; + length1; +} diff --git a/tests/baselines/reference/for-inStatementsDestructuring8.symbols b/tests/baselines/reference/for-inStatementsDestructuring8.symbols new file mode 100644 index 0000000000000..6ba919b1f29fb --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring8.symbols @@ -0,0 +1,16 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring8.ts] //// + +=== for-inStatementsDestructuring8.ts === +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring8.ts, 0, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring8.ts, 0, 20)) + +for (let { length: length1 } in obj) { +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>length1 : Symbol(length1, Decl(for-inStatementsDestructuring8.ts, 2, 10)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring8.ts, 0, 11)) + + length1 +>length1 : Symbol(length1, Decl(for-inStatementsDestructuring8.ts, 2, 10)) +} + diff --git a/tests/baselines/reference/for-inStatementsDestructuring8.types b/tests/baselines/reference/for-inStatementsDestructuring8.types new file mode 100644 index 0000000000000..a324d61a733c6 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring8.types @@ -0,0 +1,16 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring8.ts] //// + +=== for-inStatementsDestructuring8.ts === +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for (let { length: length1 } in obj) { +>length : any +>length1 : number +>obj : { [s: string]: string; } + + length1 +>length1 : number +} + diff --git a/tests/baselines/reference/for-inStatementsDestructuring9.js b/tests/baselines/reference/for-inStatementsDestructuring9.js new file mode 100644 index 0000000000000..07c64da08c756 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring9.js @@ -0,0 +1,12 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring9.ts] //// + +//// [for-inStatementsDestructuring9.ts] +let length1: number; +declare let obj: { [s: string]: string }; + +for ({ length: length1 } in obj) {} + + +//// [for-inStatementsDestructuring9.js] +var length1; +for ({ length: length1 } in obj) { } diff --git a/tests/baselines/reference/for-inStatementsDestructuring9.symbols b/tests/baselines/reference/for-inStatementsDestructuring9.symbols new file mode 100644 index 0000000000000..eac4b9aa794a3 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring9.symbols @@ -0,0 +1,15 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring9.ts] //// + +=== for-inStatementsDestructuring9.ts === +let length1: number; +>length1 : Symbol(length1, Decl(for-inStatementsDestructuring9.ts, 0, 3)) + +declare let obj: { [s: string]: string }; +>obj : Symbol(obj, Decl(for-inStatementsDestructuring9.ts, 1, 11)) +>s : Symbol(s, Decl(for-inStatementsDestructuring9.ts, 1, 20)) + +for ({ length: length1 } in obj) {} +>length : Symbol(length, Decl(for-inStatementsDestructuring9.ts, 3, 6)) +>length1 : Symbol(length1, Decl(for-inStatementsDestructuring9.ts, 0, 3)) +>obj : Symbol(obj, Decl(for-inStatementsDestructuring9.ts, 1, 11)) + diff --git a/tests/baselines/reference/for-inStatementsDestructuring9.types b/tests/baselines/reference/for-inStatementsDestructuring9.types new file mode 100644 index 0000000000000..5fc46603657b0 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring9.types @@ -0,0 +1,16 @@ +//// [tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring9.ts] //// + +=== for-inStatementsDestructuring9.ts === +let length1: number; +>length1 : number + +declare let obj: { [s: string]: string }; +>obj : { [s: string]: string; } +>s : string + +for ({ length: length1 } in obj) {} +>{ length: length1 } : { length: number; } +>length : number +>length1 : number +>obj : { [s: string]: string; } + diff --git a/tests/baselines/reference/parserForInStatement8.errors.txt b/tests/baselines/reference/parserForInStatement8.errors.txt index e7e518d42ee72..4102ef90d551f 100644 --- a/tests/baselines/reference/parserForInStatement8.errors.txt +++ b/tests/baselines/reference/parserForInStatement8.errors.txt @@ -1,20 +1,14 @@ parserForInStatement8.ts(3,10): error TS2461: Type 'string' is not an array type. -parserForInStatement8.ts(3,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. -parserForInStatement8.ts(4,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. parserForInStatement8.ts(4,11): error TS2339: Property 'x' does not exist on type 'String'. -==== parserForInStatement8.ts (4 errors) ==== +==== parserForInStatement8.ts (2 errors) ==== // repro from https://github.com/microsoft/TypeScript/issues/54769 for (let [x = 'a' in {}] in { '': 0 }) console.log(x) ~~~~~~~~~~~~~~~ !!! error TS2461: Type 'string' is not an array type. - ~~~~~~~~~~~~~~~ -!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. for (let {x = 'a' in {}} in { '': 0 }) console.log(x) - ~~~~~~~~~~~~~~~ -!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. ~ !!! error TS2339: Property 'x' does not exist on type 'String'. \ No newline at end of file diff --git a/tests/baselines/reference/parserForInStatement8.js b/tests/baselines/reference/parserForInStatement8.js index c1d737ec26e58..79a7b9c9bb82c 100644 --- a/tests/baselines/reference/parserForInStatement8.js +++ b/tests/baselines/reference/parserForInStatement8.js @@ -9,7 +9,11 @@ for (let {x = 'a' in {}} in { '': 0 }) console.log(x) //// [parserForInStatement8.js] // repro from https://github.com/microsoft/TypeScript/issues/54769 -for (var _a = (void 0)[0], x = _a === void 0 ? 'a' in {} : _a in { '': 0 }) +for (var key_1 in { '': 0 }) { + var _a = key_1[0], x = _a === void 0 ? 'a' in {} : _a; console.log(x); -for (var _b = (void 0).x, x = _b === void 0 ? 'a' in {} : _b in { '': 0 }) +} +for (var key_2 in { '': 0 }) { + var _b = key_2.x, x = _b === void 0 ? 'a' in {} : _b; console.log(x); +} diff --git a/tests/baselines/reference/parserForStatement5.errors.txt b/tests/baselines/reference/parserForStatement5.errors.txt index 18b24f34f0551..0624812994c31 100644 --- a/tests/baselines/reference/parserForStatement5.errors.txt +++ b/tests/baselines/reference/parserForStatement5.errors.txt @@ -1,11 +1,8 @@ -parserForStatement5.ts(1,6): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. parserForStatement5.ts(1,12): error TS2304: Cannot find name 'b'. -==== parserForStatement5.ts (2 errors) ==== +==== parserForStatement5.ts (1 errors) ==== for ({} in b) { - ~~ -!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. ~ !!! error TS2304: Cannot find name 'b'. } \ No newline at end of file diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts new file mode 100644 index 0000000000000..238d147892b01 --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring5.ts @@ -0,0 +1,6 @@ +// @target: es5, esnext + +let a: string; +declare let obj: { [s: string]: string }; + +for ([a] in obj) {} diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts new file mode 100644 index 0000000000000..e9d10130ff952 --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring6.ts @@ -0,0 +1,7 @@ +// @target: es5, esnext + +let b: number; +let c: string[]; +declare let obj: { [s: string]: string }; + +for ([b, ...c] in obj) {} diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts new file mode 100644 index 0000000000000..12d0186d7fba1 --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring7.ts @@ -0,0 +1,8 @@ +// @target: es5, esnext + +declare let obj: { [s: string]: string }; + +for (let [b, ...c] in obj) { + b; + c; +} diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring8.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring8.ts new file mode 100644 index 0000000000000..93613a58e6f9e --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring8.ts @@ -0,0 +1,5 @@ +declare let obj: { [s: string]: string }; + +for (let { length: length1 } in obj) { + length1 +} diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring9.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring9.ts new file mode 100644 index 0000000000000..9309cc6747bab --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring9.ts @@ -0,0 +1,4 @@ +let length1: number; +declare let obj: { [s: string]: string }; + +for ({ length: length1 } in obj) {}