@@ -7764,16 +7764,17 @@ namespace ts {
7764
7764
}
7765
7765
7766
7766
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);
7777
7778
}
7778
7779
return false;
7779
7780
}
@@ -7788,6 +7789,10 @@ namespace ts {
7788
7789
return false;
7789
7790
}
7790
7791
7792
+ function rootContainsMatchingReference(source: Node, target: Node) {
7793
+ return target.kind === SyntaxKind.PropertyAccessExpression && containsMatchingReference(source, (<PropertyAccessExpression>target).expression);
7794
+ }
7795
+
7791
7796
function isOrContainsMatchingReference(source: Node, target: Node) {
7792
7797
return isMatchingReference(source, target) || containsMatchingReference(source, target);
7793
7798
}
@@ -8031,6 +8036,12 @@ namespace ts {
8031
8036
getInitialTypeOfBindingElement(<BindingElement>node);
8032
8037
}
8033
8038
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
+
8034
8045
function getReferenceCandidate(node: Expression): Expression {
8035
8046
switch (node.kind) {
8036
8047
case SyntaxKind.ParenthesizedExpression:
@@ -8153,19 +8164,9 @@ namespace ts {
8153
8164
const node = flow.node;
8154
8165
// Assignments only narrow the computed type if the declared type is a union type. Thus, we
8155
8166
// 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.
8166
8167
if (isMatchingReference(reference, node)) {
8167
8168
return declaredType.flags & TypeFlags.Union ?
8168
- getAssignmentReducedType(<UnionType>declaredType, getAssignedType(<Expression> node)) :
8169
+ getAssignmentReducedType(<UnionType>declaredType, getInitialOrAssignedType( node)) :
8169
8170
declaredType;
8170
8171
}
8171
8172
// We didn't have a direct match. However, if the reference is a dotted name, this
@@ -8297,6 +8298,9 @@ namespace ts {
8297
8298
if (isMatchingPropertyAccess(expr)) {
8298
8299
return narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy));
8299
8300
}
8301
+ if (rootContainsMatchingReference(reference, expr)) {
8302
+ return declaredType;
8303
+ }
8300
8304
return type;
8301
8305
}
8302
8306
@@ -8329,6 +8333,9 @@ namespace ts {
8329
8333
if (isMatchingPropertyAccess(right)) {
8330
8334
return narrowTypeByDiscriminant(type, <PropertyAccessExpression>right, t => narrowTypeByEquality(t, operator, left, assumeTrue));
8331
8335
}
8336
+ if (rootContainsMatchingReference(reference, left) || rootContainsMatchingReference(reference, right)) {
8337
+ return declaredType;
8338
+ }
8332
8339
break;
8333
8340
case SyntaxKind.InstanceOfKeyword:
8334
8341
return narrowTypeByInstanceof(type, expr, assumeTrue);
0 commit comments