Skip to content

Commit 00f41e5

Browse files
committed
Less aggressive reduction of intersection types
1 parent 4c76bae commit 00f41e5

File tree

1 file changed

+38
-28
lines changed

1 file changed

+38
-28
lines changed

src/compiler/checker.ts

+38-28
Original file line numberDiff line numberDiff line change
@@ -15310,7 +15310,7 @@ namespace ts {
1531015310
objectFlags & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeVariables) ||
1531115311
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ||
1531215312
objectFlags & ObjectFlags.Mapped ||
15313-
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeVariables(<UnionOrIntersectionType>type));
15313+
type.flags & TypeFlags.UnionOrIntersection && !(type.flags & TypeFlags.EnumLiteral) && couldUnionOrIntersectionContainTypeVariables(<UnionOrIntersectionType>type));
1531415314
}
1531515315

1531615316
function couldUnionOrIntersectionContainTypeVariables(type: UnionOrIntersectionType): boolean {
@@ -15487,37 +15487,47 @@ namespace ts {
1548715487
inferFromTypeArguments(source.aliasTypeArguments, target.aliasTypeArguments!, getAliasVariances(source.aliasSymbol));
1548815488
return;
1548915489
}
15490-
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && !(source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.EnumLiteral) ||
15491-
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
15492-
// Source and target are both unions or both intersections. If source and target
15493-
// are the same type, just relate each constituent type to itself.
15494-
if (source === target) {
15495-
for (const t of (<UnionOrIntersectionType>source).types) {
15496-
inferFromTypes(t, t);
15490+
if (source === target && source.flags & TypeFlags.UnionOrIntersection) {
15491+
// When source and target are the same union or intersection type, just relate each constituent
15492+
// type to itself.
15493+
for (const t of (<UnionOrIntersectionType>source).types) {
15494+
inferFromTypes(t, t);
15495+
}
15496+
return;
15497+
}
15498+
if (target.flags & TypeFlags.Union) {
15499+
if (source.flags & TypeFlags.Union) {
15500+
// First, infer between identically matching source and target constituents and remove the
15501+
// matching types.
15502+
const [tempSources, tempTargets] = inferFromMatchingTypes((<UnionType>source).types, (<UnionType>target).types, isTypeOrBaseIdenticalTo);
15503+
// Next, infer between closely matching source and target constituents and remove
15504+
// the matching types. Types closely match when they are instantiations of the same
15505+
// object type or instantiations of the same type alias.
15506+
const [sources, targets] = inferFromMatchingTypes(tempSources, tempTargets, isTypeCloselyMatchedBy);
15507+
if (sources.length === 0 || targets.length === 0) {
15508+
return;
1549715509
}
15498-
return;
15510+
source = getUnionType(sources);
15511+
target = getUnionType(targets);
1549915512
}
15500-
// First, infer between exactly matching source and target constituents and remove
15501-
// the matching types. Types exactly match when they are identical or, in union
15502-
// types, when the source is a literal and the target is the corresponding primitive.
15503-
const matching = target.flags & TypeFlags.Union ? isTypeOrBaseIdenticalTo : isTypeIdenticalTo;
15504-
const [tempSources, tempTargets] = inferFromMatchingTypes((<UnionOrIntersectionType>source).types, (<UnionOrIntersectionType>target).types, matching);
15505-
// Next, infer between closely matching source and target constituents and remove
15506-
// the matching types. Types closely match when they are instantiations of the same
15507-
// object type or instantiations of the same type alias.
15508-
const [sources, targets] = inferFromMatchingTypes(tempSources, tempTargets, isTypeCloselyMatchedBy);
15509-
if (sources.length === 0 || targets.length === 0) {
15510-
return;
15513+
else {
15514+
if (inferFromMatchingType(source, (<UnionType>target).types, isTypeOrBaseIdenticalTo)) return;
15515+
if (inferFromMatchingType(source, (<UnionType>target).types, isTypeCloselyMatchedBy)) return;
1551115516
}
15512-
source = source.flags & TypeFlags.Union ? getUnionType(sources) : getIntersectionType(sources);
15513-
target = target.flags & TypeFlags.Union ? getUnionType(targets) : getIntersectionType(targets);
1551415517
}
15515-
else if (target.flags & TypeFlags.Union && !(target.flags & TypeFlags.EnumLiteral) || target.flags & TypeFlags.Intersection) {
15516-
// This block of code is an optimized version of the block above for the simpler case
15517-
// of a singleton source type.
15518-
const matching = target.flags & TypeFlags.Union ? isTypeOrBaseIdenticalTo : isTypeIdenticalTo;
15519-
if (inferFromMatchingType(source, (<UnionOrIntersectionType>target).types, matching)) return;
15520-
if (inferFromMatchingType(source, (<UnionOrIntersectionType>target).types, isTypeCloselyMatchedBy)) return;
15518+
else if (target.flags & TypeFlags.Intersection && some((<IntersectionType>target).types, t => !!getInferenceInfoForType(t))) {
15519+
if (source.flags & TypeFlags.Intersection) {
15520+
// Infer between identically matching source and target constituents and remove the matching types.
15521+
const [sources, targets] = inferFromMatchingTypes((<IntersectionType>source).types, (<IntersectionType>target).types, isTypeIdenticalTo);
15522+
if (sources.length === 0 || targets.length === 0) {
15523+
return;
15524+
}
15525+
source = getIntersectionType(sources);
15526+
target = getIntersectionType(targets);
15527+
}
15528+
else if (!(source.flags & TypeFlags.Union)) {
15529+
if (inferFromMatchingType(source, (<IntersectionType>target).types, isTypeIdenticalTo)) return;
15530+
}
1552115531
}
1552215532
else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) {
1552315533
target = getActualTypeVariable(target);

0 commit comments

Comments
 (0)