diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff1da5db911..08bd2815321 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10851,12 +10851,34 @@ namespace ts { } } if (reportErrors) { - const discriminantType = findMatchingDiscriminantType(source, target); - isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true); + const bestMatchingType = + findMatchingDiscriminantType(source, target) || + findMatchingTypeReferenceOrTypeAliasReference(source, target); + + isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true); } return Ternary.False; } + function findMatchingTypeReferenceOrTypeAliasReference(source: Type, unionTarget: UnionOrIntersectionType) { + if (source.flags & TypeFlags.Object && (source as ObjectType).objectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union) { + return find(unionTarget.types, t => { + if (t.flags & TypeFlags.Object) { + if ((source as ObjectType).objectFlags & (t as ObjectType).objectFlags & ObjectFlags.Reference) { + return (source as TypeReference).target === (t as TypeReference).target; + } + if ((source as ObjectType).objectFlags & (t as ObjectType).objectFlags & ObjectFlags.Anonymous) { + // TODO (drosen): Not sure why the following isn't sufficient. + // return !!(source as AnonymousType).aliasSymbol && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol; + return false; + } + } + return false; + }); + } + } + + // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) { let match: Type | undefined;