@@ -391,7 +391,7 @@ namespace ts {
391391
392392 const tupleTypes = createMap<GenericType>();
393393 const unionTypes = createMap<UnionType>();
394- const intersectionTypes = createMap<IntersectionType >();
394+ const intersectionTypes = createMap<Type >();
395395 const literalTypes = createMap<LiteralType>();
396396 const indexedAccessTypes = createMap<IndexedAccessType>();
397397 const substitutionTypes = createMap<SubstitutionType>();
@@ -9838,6 +9838,15 @@ namespace ts {
98389838 return true;
98399839 }
98409840
9841+ function createIntersectionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray<Type>) {
9842+ const result = <IntersectionType>createType(TypeFlags.Intersection);
9843+ result.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
9844+ result.types = types;
9845+ result.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`.
9846+ result.aliasTypeArguments = aliasTypeArguments;
9847+ return result;
9848+ }
9849+
98419850 // We normalize combinations of intersection and union types based on the distributive property of the '&'
98429851 // operator. Specifically, because X & (A | B) is equivalent to X & A | X & B, we can transform intersection
98439852 // types with union type constituents into equivalent union types with intersection type constituents and
@@ -9875,31 +9884,31 @@ namespace ts {
98759884 if (typeSet.length === 1) {
98769885 return typeSet[0];
98779886 }
9878- if (includes & TypeFlags.Union) {
9879- if (intersectUnionsOfPrimitiveTypes(typeSet)) {
9880- // When the intersection creates a reduced set (which might mean that *all* union types have
9881- // disappeared), we restart the operation to get a new set of combined flags. Once we have
9882- // reduced we'll never reduce again, so this occurs at most once.
9883- return getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
9884- }
9885- // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
9886- // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
9887- const unionIndex = findIndex(typeSet, t => (t.flags & TypeFlags.Union) !== 0);
9888- const unionType = <UnionType>typeSet[unionIndex];
9889- return getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
9890- UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
9891- }
98929887 const id = getTypeListId(typeSet);
9893- let type = intersectionTypes.get(id);
9894- if (!type) {
9895- type = <IntersectionType>createType(TypeFlags.Intersection);
9896- intersectionTypes.set(id, type);
9897- type.objectFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable);
9898- type.types = typeSet;
9899- type.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`.
9900- type.aliasTypeArguments = aliasTypeArguments;
9888+ let result = intersectionTypes.get(id);
9889+ if (!result) {
9890+ if (includes & TypeFlags.Union) {
9891+ if (intersectUnionsOfPrimitiveTypes(typeSet)) {
9892+ // When the intersection creates a reduced set (which might mean that *all* union types have
9893+ // disappeared), we restart the operation to get a new set of combined flags. Once we have
9894+ // reduced we'll never reduce again, so this occurs at most once.
9895+ result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
9896+ }
9897+ else {
9898+ // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
9899+ // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
9900+ const unionIndex = findIndex(typeSet, t => (t.flags & TypeFlags.Union) !== 0);
9901+ const unionType = <UnionType>typeSet[unionIndex];
9902+ result = getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
9903+ UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
9904+ }
9905+ }
9906+ else {
9907+ result = createIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
9908+ }
9909+ intersectionTypes.set(id, result);
99019910 }
9902- return type ;
9911+ return result ;
99039912 }
99049913
99059914 function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
0 commit comments