@@ -7764,16 +7764,17 @@ namespace ts {
77647764 }
77657765
77667766 function isMatchingReference(source: Node, target: Node): boolean {
7767- if (source.kind === target.kind) {
7768- switch (source.kind) {
7769- case SyntaxKind.Identifier:
7770- return getResolvedSymbol(<Identifier>source) === getResolvedSymbol(<Identifier>target);
7771- case SyntaxKind.ThisKeyword:
7772- return true;
7773- case SyntaxKind.PropertyAccessExpression:
7774- return (<PropertyAccessExpression>source).name.text === (<PropertyAccessExpression>target).name.text &&
7775- isMatchingReference((<PropertyAccessExpression>source).expression, (<PropertyAccessExpression>target).expression);
7776- }
7767+ switch (source.kind) {
7768+ case SyntaxKind.Identifier:
7769+ return target.kind === SyntaxKind.Identifier && getResolvedSymbol(<Identifier>source) === getResolvedSymbol(<Identifier>target) ||
7770+ (target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement) &&
7771+ getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(<Identifier>source)) === getSymbolOfNode(target);
7772+ case SyntaxKind.ThisKeyword:
7773+ return target.kind === SyntaxKind.ThisKeyword;
7774+ case SyntaxKind.PropertyAccessExpression:
7775+ return target.kind === SyntaxKind.PropertyAccessExpression &&
7776+ (<PropertyAccessExpression>source).name.text === (<PropertyAccessExpression>target).name.text &&
7777+ isMatchingReference((<PropertyAccessExpression>source).expression, (<PropertyAccessExpression>target).expression);
77777778 }
77787779 return false;
77797780 }
@@ -7788,6 +7789,10 @@ namespace ts {
77887789 return false;
77897790 }
77907791
7792+ function rootContainsMatchingReference(source: Node, target: Node) {
7793+ return target.kind === SyntaxKind.PropertyAccessExpression && containsMatchingReference(source, (<PropertyAccessExpression>target).expression);
7794+ }
7795+
77917796 function isOrContainsMatchingReference(source: Node, target: Node) {
77927797 return isMatchingReference(source, target) || containsMatchingReference(source, target);
77937798 }
@@ -8031,6 +8036,12 @@ namespace ts {
80318036 getInitialTypeOfBindingElement(<BindingElement>node);
80328037 }
80338038
8039+ function getInitialOrAssignedType(node: VariableDeclaration | BindingElement | Expression) {
8040+ return node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ?
8041+ getInitialType(<VariableDeclaration | BindingElement>node) :
8042+ getAssignedType(<Expression>node);
8043+ }
8044+
80348045 function getReferenceCandidate(node: Expression): Expression {
80358046 switch (node.kind) {
80368047 case SyntaxKind.ParenthesizedExpression:
@@ -8153,19 +8164,9 @@ namespace ts {
81538164 const node = flow.node;
81548165 // Assignments only narrow the computed type if the declared type is a union type. Thus, we
81558166 // only need to evaluate the assigned type if the declared type is a union type.
8156- if ((node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) &&
8157- reference.kind === SyntaxKind.Identifier &&
8158- getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(<Identifier>reference)) === getSymbolOfNode(node)) {
8159- return declaredType.flags & TypeFlags.Union ?
8160- getAssignmentReducedType(<UnionType>declaredType, getInitialType(<VariableDeclaration | BindingElement>node)) :
8161- declaredType;
8162- }
8163- // If the node is not a variable declaration or binding element, it is an identifier
8164- // or a dotted name that is the target of an assignment. If we have a match, reduce
8165- // the declared type by the assigned type.
81668167 if (isMatchingReference(reference, node)) {
81678168 return declaredType.flags & TypeFlags.Union ?
8168- getAssignmentReducedType(<UnionType>declaredType, getAssignedType(<Expression> node)) :
8169+ getAssignmentReducedType(<UnionType>declaredType, getInitialOrAssignedType( node)) :
81698170 declaredType;
81708171 }
81718172 // We didn't have a direct match. However, if the reference is a dotted name, this
@@ -8297,6 +8298,9 @@ namespace ts {
82978298 if (isMatchingPropertyAccess(expr)) {
82988299 return narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy));
82998300 }
8301+ if (rootContainsMatchingReference(reference, expr)) {
8302+ return declaredType;
8303+ }
83008304 return type;
83018305 }
83028306
@@ -8329,6 +8333,9 @@ namespace ts {
83298333 if (isMatchingPropertyAccess(right)) {
83308334 return narrowTypeByDiscriminant(type, <PropertyAccessExpression>right, t => narrowTypeByEquality(t, operator, left, assumeTrue));
83318335 }
8336+ if (rootContainsMatchingReference(reference, left) || rootContainsMatchingReference(reference, right)) {
8337+ return declaredType;
8338+ }
83328339 break;
83338340 case SyntaxKind.InstanceOfKeyword:
83348341 return narrowTypeByInstanceof(type, expr, assumeTrue);
0 commit comments