From 125dd57a757612367bcf495ed3070bb932ae75ed Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 8 Feb 2017 13:28:23 -0800 Subject: [PATCH] Fix assigned type of assignment nested in literals Fixes #12946 --- src/compiler/checker.ts | 10 +++++- .../reference/assignmentNestedInLiterals.js | 13 +++++++ .../assignmentNestedInLiterals.symbols | 25 +++++++++++++ .../assignmentNestedInLiterals.types | 35 +++++++++++++++++++ .../compiler/assignmentNestedInLiterals.ts | 6 ++++ 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/assignmentNestedInLiterals.js create mode 100644 tests/baselines/reference/assignmentNestedInLiterals.symbols create mode 100644 tests/baselines/reference/assignmentNestedInLiterals.types create mode 100644 tests/cases/compiler/assignmentNestedInLiterals.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4423b574e3..428a4e6eee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9469,11 +9469,19 @@ namespace ts { } function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type { - return node.parent.kind === SyntaxKind.ArrayLiteralExpression || node.parent.kind === SyntaxKind.PropertyAssignment ? + const isDestructuringDefaultAssignment = + node.parent.kind === SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) || + node.parent.kind === SyntaxKind.PropertyAssignment && isDestructuringAssignmentTarget(node.parent.parent); + return isDestructuringDefaultAssignment ? getTypeWithDefault(getAssignedType(node), node.right) : getTypeOfExpression(node.right); } + function isDestructuringAssignmentTarget(parent: Node) { + return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent || + parent.parent.kind === SyntaxKind.ForOfStatement && (parent.parent as ForOfStatement).initializer === parent; + } + function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type { return getTypeOfDestructuredArrayElement(getAssignedType(node), indexOf(node.elements, element)); } diff --git a/tests/baselines/reference/assignmentNestedInLiterals.js b/tests/baselines/reference/assignmentNestedInLiterals.js new file mode 100644 index 0000000000..cd4bc6c669 --- /dev/null +++ b/tests/baselines/reference/assignmentNestedInLiterals.js @@ -0,0 +1,13 @@ +//// [assignmentNestedInLiterals.ts] +var target, x, y; +target = [x = 1, y = x]; + +var aegis, a, b; +aegis = { x: a = 1, y: b = a }; + + +//// [assignmentNestedInLiterals.js] +var target, x, y; +target = [x = 1, y = x]; +var aegis, a, b; +aegis = { x: a = 1, y: b = a }; diff --git a/tests/baselines/reference/assignmentNestedInLiterals.symbols b/tests/baselines/reference/assignmentNestedInLiterals.symbols new file mode 100644 index 0000000000..90edd9ed04 --- /dev/null +++ b/tests/baselines/reference/assignmentNestedInLiterals.symbols @@ -0,0 +1,25 @@ +=== tests/cases/compiler/assignmentNestedInLiterals.ts === +var target, x, y; +>target : Symbol(target, Decl(assignmentNestedInLiterals.ts, 0, 3)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 0, 11)) +>y : Symbol(y, Decl(assignmentNestedInLiterals.ts, 0, 14)) + +target = [x = 1, y = x]; +>target : Symbol(target, Decl(assignmentNestedInLiterals.ts, 0, 3)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 0, 11)) +>y : Symbol(y, Decl(assignmentNestedInLiterals.ts, 0, 14)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 0, 11)) + +var aegis, a, b; +>aegis : Symbol(aegis, Decl(assignmentNestedInLiterals.ts, 3, 3)) +>a : Symbol(a, Decl(assignmentNestedInLiterals.ts, 3, 10)) +>b : Symbol(b, Decl(assignmentNestedInLiterals.ts, 3, 13)) + +aegis = { x: a = 1, y: b = a }; +>aegis : Symbol(aegis, Decl(assignmentNestedInLiterals.ts, 3, 3)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 4, 9)) +>a : Symbol(a, Decl(assignmentNestedInLiterals.ts, 3, 10)) +>y : Symbol(y, Decl(assignmentNestedInLiterals.ts, 4, 19)) +>b : Symbol(b, Decl(assignmentNestedInLiterals.ts, 3, 13)) +>a : Symbol(a, Decl(assignmentNestedInLiterals.ts, 3, 10)) + diff --git a/tests/baselines/reference/assignmentNestedInLiterals.types b/tests/baselines/reference/assignmentNestedInLiterals.types new file mode 100644 index 0000000000..8c4d5aadc7 --- /dev/null +++ b/tests/baselines/reference/assignmentNestedInLiterals.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/assignmentNestedInLiterals.ts === +var target, x, y; +>target : any +>x : any +>y : any + +target = [x = 1, y = x]; +>target = [x = 1, y = x] : number[] +>target : any +>[x = 1, y = x] : number[] +>x = 1 : 1 +>x : any +>1 : 1 +>y = x : number +>y : any +>x : number + +var aegis, a, b; +>aegis : any +>a : any +>b : any + +aegis = { x: a = 1, y: b = a }; +>aegis = { x: a = 1, y: b = a } : { x: number; y: number; } +>aegis : any +>{ x: a = 1, y: b = a } : { x: number; y: number; } +>x : number +>a = 1 : 1 +>a : any +>1 : 1 +>y : number +>b = a : number +>b : any +>a : number + diff --git a/tests/cases/compiler/assignmentNestedInLiterals.ts b/tests/cases/compiler/assignmentNestedInLiterals.ts new file mode 100644 index 0000000000..5b1f52cb45 --- /dev/null +++ b/tests/cases/compiler/assignmentNestedInLiterals.ts @@ -0,0 +1,6 @@ +// @noImplicitAny: true +var target, x, y; +target = [x = 1, y = x]; + +var aegis, a, b; +aegis = { x: a = 1, y: b = a };