Reset narrowing of 'x.y' only when 'x' has a narrowable type

This commit is contained in:
Anders Hejlsberg 2018-10-24 13:51:11 -07:00
parent eadf44d073
commit 6fbd2a5f59

View File

@ -14340,6 +14340,11 @@ namespace ts {
return false;
}
function hasNarrowableDeclaredType(expr: Node) {
const type = getDeclaredTypeOfReference(expr);
return !!(type && type.flags & TypeFlags.Union);
}
function findDiscriminantProperties(sourceProperties: Symbol[], target: Type): Symbol[] | undefined {
let result: Symbol[] | undefined;
for (const sourceProperty of sourceProperties) {
@ -15373,9 +15378,9 @@ namespace ts {
// We have '==', '!=', '====', or !==' operator with 'typeof xxx' and string literal operands
const target = getReferenceCandidate(typeOfExpr.expression);
if (!isMatchingReference(reference, target)) {
// For a reference of the form 'x.y', a 'typeof x === ...' type guard resets the
// narrowed type of 'y' to its declared type.
if (containsMatchingReference(reference, target)) {
// For a reference of the form 'x.y', where 'x' has a narrowable declared type, a
// 'typeof x === ...' type guard resets the narrowed type of 'y' to its declared type.
if (containsMatchingReference(reference, target) && hasNarrowableDeclaredType(target)) {
return declaredType;
}
return type;
@ -15516,9 +15521,9 @@ namespace ts {
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
const left = getReferenceCandidate(expr.left);
if (!isMatchingReference(reference, left)) {
// For a reference of the form 'x.y', an 'x instanceof T' type guard resets the
// narrowed type of 'y' to its declared type.
if (containsMatchingReference(reference, left)) {
// For a reference of the form 'x.y', where 'x' has a narrowable declared type, an
// 'x instanceof T' type guard resets the narrowed type of 'y' to its declared type.
if (containsMatchingReference(reference, left) && hasNarrowableDeclaredType(left)) {
return declaredType;
}
return type;