Reduce union and intersection targets when source is singleton type

This commit is contained in:
Anders Hejlsberg 2019-07-17 14:53:29 -07:00
parent d8b191a671
commit 5a45d5aed8

View file

@ -15500,15 +15500,10 @@ namespace ts {
// of all their possible values.
let matchingTypes: Type[] | undefined;
for (const t of (<UnionOrIntersectionType>source).types) {
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>target).types)) {
(matchingTypes || (matchingTypes = [])).push(t);
inferFromTypes(t, t);
}
else if (t.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral)) {
const b = getBaseTypeOfLiteralType(t);
if (typeIdenticalToSomeType(b, (<UnionOrIntersectionType>target).types)) {
(matchingTypes || (matchingTypes = [])).push(t, b);
}
const matched = findMatchedType(t, <UnionOrIntersectionType>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(<UnionOrIntersectionType>target, matchingTypes);
}
}
else if (target.flags & TypeFlags.Union && !(target.flags & TypeFlags.EnumLiteral) || target.flags & TypeFlags.Intersection) {
const matched = findMatchedType(source, <UnionOrIntersectionType>target);
if (matched) {
inferFromTypes(matched, matched);
source = target.flags & TypeFlags.Union ? neverType : unknownType;
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>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.