diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 04c12eb613c..691d7451895 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7764,16 +7764,17 @@ namespace ts { } function isMatchingReference(source: Node, target: Node): boolean { - if (source.kind === target.kind) { - switch (source.kind) { - case SyntaxKind.Identifier: - return getResolvedSymbol(source) === getResolvedSymbol(target); - case SyntaxKind.ThisKeyword: - return true; - case SyntaxKind.PropertyAccessExpression: - return (source).name.text === (target).name.text && - isMatchingReference((source).expression, (target).expression); - } + switch (source.kind) { + case SyntaxKind.Identifier: + return target.kind === SyntaxKind.Identifier && getResolvedSymbol(source) === getResolvedSymbol(target) || + (target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement) && + getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source)) === getSymbolOfNode(target); + case SyntaxKind.ThisKeyword: + return target.kind === SyntaxKind.ThisKeyword; + case SyntaxKind.PropertyAccessExpression: + return target.kind === SyntaxKind.PropertyAccessExpression && + (source).name.text === (target).name.text && + isMatchingReference((source).expression, (target).expression); } return false; } @@ -8031,6 +8032,12 @@ namespace ts { getInitialTypeOfBindingElement(node); } + function getInitialOrAssignedType(node: VariableDeclaration | BindingElement | Expression) { + return node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ? + getInitialType(node) : + getAssignedType(node); + } + function getReferenceCandidate(node: Expression): Expression { switch (node.kind) { case SyntaxKind.ParenthesizedExpression: @@ -8153,19 +8160,9 @@ namespace ts { const node = flow.node; // Assignments only narrow the computed type if the declared type is a union type. Thus, we // only need to evaluate the assigned type if the declared type is a union type. - if ((node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) && - reference.kind === SyntaxKind.Identifier && - getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(reference)) === getSymbolOfNode(node)) { - return declaredType.flags & TypeFlags.Union ? - getAssignmentReducedType(declaredType, getInitialType(node)) : - declaredType; - } - // If the node is not a variable declaration or binding element, it is an identifier - // or a dotted name that is the target of an assignment. If we have a match, reduce - // the declared type by the assigned type. if (isMatchingReference(reference, node)) { return declaredType.flags & TypeFlags.Union ? - getAssignmentReducedType(declaredType, getAssignedType(node)) : + getAssignmentReducedType(declaredType, getInitialOrAssignedType(node)) : declaredType; } // We didn't have a direct match. However, if the reference is a dotted name, this