In getContextualTypeForBinaryOperand, only need to look for = assignment operator, not e.g. += (#20037)

* In `getContextualTypeForBinaryOperand`, only need to look for `=` assignment operator, not e.g. `+=`

* isNonContextualBinaryExpression -> isContextSensitiveAssignment
This commit is contained in:
Andy
2017-11-17 07:29:32 -08:00
committed by GitHub
parent 36f7f307f5
commit 46c0edcebd

View File

@@ -13862,48 +13862,43 @@ namespace ts {
return undefined;
}
function getContextualTypeForBinaryOperand(node: Expression): Type {
function getContextualTypeForBinaryOperand(node: Expression): Type | undefined {
const binaryExpression = <BinaryExpression>node.parent;
const operator = binaryExpression.operatorToken.kind;
if (isAssignmentOperator(operator)) {
if (node === binaryExpression.right) {
// Don't do this for special property assignments to avoid circularity
switch (getSpecialPropertyAssignmentKind(binaryExpression)) {
case SpecialPropertyAssignmentKind.None:
break;
case SpecialPropertyAssignmentKind.Property:
// If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration.
// See `bindStaticPropertyAssignment` in `binder.ts`.
if (!binaryExpression.left.symbol) {
break;
}
// falls through
case SpecialPropertyAssignmentKind.ExportsProperty:
case SpecialPropertyAssignmentKind.ModuleExports:
case SpecialPropertyAssignmentKind.PrototypeProperty:
case SpecialPropertyAssignmentKind.ThisProperty:
return undefined;
}
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
return getTypeOfExpression(binaryExpression.left);
}
const { left, operatorToken, right } = binaryExpression;
switch (operatorToken.kind) {
case SyntaxKind.EqualsToken:
return node === right && isContextSensitiveAssignment(binaryExpression) ? getTypeOfExpression(left) : undefined;
case SyntaxKind.BarBarToken:
// When an || expression has a contextual type, the operands are contextually typed by that type. When an ||
// expression has no contextual type, the right operand is contextually typed by the type of the left operand.
const type = getContextualType(binaryExpression);
return !type && node === right ? getTypeOfExpression(left, /*cache*/ true) : type;
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.CommaToken:
return node === right ? getContextualType(binaryExpression) : undefined;
default:
return undefined;
}
else if (operator === SyntaxKind.BarBarToken) {
// When an || expression has a contextual type, the operands are contextually typed by that type. When an ||
// expression has no contextual type, the right operand is contextually typed by the type of the left operand.
let type = getContextualType(binaryExpression);
if (!type && node === binaryExpression.right) {
type = getTypeOfExpression(binaryExpression.left, /*cache*/ true);
}
return type;
}
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
// Don't do this for special property assignments to avoid circularity.
function isContextSensitiveAssignment(binaryExpression: BinaryExpression): boolean {
const kind = getSpecialPropertyAssignmentKind(binaryExpression);
switch (kind) {
case SpecialPropertyAssignmentKind.None:
return true;
case SpecialPropertyAssignmentKind.Property:
// If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration.
// See `bindStaticPropertyAssignment` in `binder.ts`.
return !binaryExpression.left.symbol;
case SpecialPropertyAssignmentKind.ExportsProperty:
case SpecialPropertyAssignmentKind.ModuleExports:
case SpecialPropertyAssignmentKind.PrototypeProperty:
case SpecialPropertyAssignmentKind.ThisProperty:
return false;
default:
Debug.assertNever(kind);
}
else if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.CommaToken) {
if (node === binaryExpression.right) {
return getContextualType(binaryExpression);
}
}
return undefined;
}
function getTypeOfPropertyOfContextualType(type: Type, name: __String) {