Skip to content

Commit 3e1b443

Browse files
committed
Deduplicate intersection types before distributing over union types
1 parent 88b7d53 commit 3e1b443

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5637,6 +5637,7 @@ namespace ts {
56375637
containsString?: boolean;
56385638
containsNumber?: boolean;
56395639
containsStringOrNumberLiteral?: boolean;
5640+
unionIndex?: number;
56405641
}
56415642

56425643
function binarySearchTypes(types: Type[], type: Type): number {
@@ -5831,6 +5832,9 @@ namespace ts {
58315832
typeSet.containsAny = true;
58325833
}
58335834
else if (!(type.flags & TypeFlags.Never) && (strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) {
5835+
if (type.flags & TypeFlags.Union && typeSet.unionIndex === undefined) {
5836+
typeSet.unionIndex = typeSet.length;
5837+
}
58345838
typeSet.push(type);
58355839
}
58365840
}
@@ -5857,15 +5861,6 @@ namespace ts {
58575861
if (types.length === 0) {
58585862
return emptyObjectType;
58595863
}
5860-
for (let i = 0; i < types.length; i++) {
5861-
const type = types[i];
5862-
if (type.flags & TypeFlags.Union) {
5863-
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
5864-
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
5865-
return getUnionType(map((<UnionType>type).types, t => getIntersectionType(replaceElement(types, i, t))),
5866-
/*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
5867-
}
5868-
}
58695864
const typeSet = [] as TypeSet;
58705865
addTypesToIntersection(typeSet, types);
58715866
if (typeSet.containsAny) {
@@ -5874,6 +5869,14 @@ namespace ts {
58745869
if (typeSet.length === 1) {
58755870
return typeSet[0];
58765871
}
5872+
const unionIndex = typeSet.unionIndex;
5873+
if (unionIndex !== undefined) {
5874+
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
5875+
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
5876+
const unionType = <UnionType>typeSet[unionIndex];
5877+
return getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
5878+
/*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
5879+
}
58775880
const id = getTypeListId(typeSet);
58785881
let type = intersectionTypes[id];
58795882
if (!type) {

0 commit comments

Comments
 (0)