diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 75b12ee37bb..1a2fc79534e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15500,15 +15500,10 @@ namespace ts { // of all their possible values. let matchingTypes: Type[] | undefined; for (const t of (source).types) { - if (typeIdenticalToSomeType(t, (target).types)) { - (matchingTypes || (matchingTypes = [])).push(t); - inferFromTypes(t, t); - } - else if (t.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral)) { - const b = getBaseTypeOfLiteralType(t); - if (typeIdenticalToSomeType(b, (target).types)) { - (matchingTypes || (matchingTypes = [])).push(t, b); - } + const matched = findMatchedType(t, target); + if (matched) { + (matchingTypes || (matchingTypes = [])).push(matched); + inferFromTypes(matched, matched); } } // Next, to improve the quality of inferences, reduce the source and target types by @@ -15519,6 +15514,14 @@ namespace ts { target = removeTypesFromUnionOrIntersection(target, matchingTypes); } } + else if (target.flags & TypeFlags.Union && !(target.flags & TypeFlags.EnumLiteral) || target.flags & TypeFlags.Intersection) { + const matched = findMatchedType(source, target); + if (matched) { + inferFromTypes(matched, matched); + source = target.flags & TypeFlags.Union ? neverType : unknownType; + target = removeTypesFromUnionOrIntersection(target, [matched]); + } + } else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) { target = getActualTypeVariable(target); } @@ -15955,6 +15958,19 @@ namespace ts { return false; } + function findMatchedType(type: Type, target: UnionOrIntersectionType) { + if (typeIdenticalToSomeType(type, target.types)) { + return type; + } + if (type.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral) && target.flags & TypeFlags.Union) { + const base = getBaseTypeOfLiteralType(type); + if (typeIdenticalToSomeType(base, target.types)) { + return base; + } + } + return undefined; + } + /** * Return a new union or intersection type computed by removing a given set of types * from a given union or intersection type.