@@ -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>();
@@ -9844,6 +9844,15 @@ namespace ts {
98449844 return true;
98459845 }
98469846
9847+ function createIntersectionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray<Type>) {
9848+ const result = <IntersectionType>createType(TypeFlags.Intersection);
9849+ result.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
9850+ result.types = types;
9851+ result.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`.
9852+ result.aliasTypeArguments = aliasTypeArguments;
9853+ return result;
9854+ }
9855+
98479856 // We normalize combinations of intersection and union types based on the distributive property of the '&'
98489857 // operator. Specifically, because X & (A | B) is equivalent to X & A | X & B, we can transform intersection
98499858 // types with union type constituents into equivalent union types with intersection type constituents and
@@ -9881,31 +9890,31 @@ namespace ts {
98819890 if (typeSet.length === 1) {
98829891 return typeSet[0];
98839892 }
9884- if (includes & TypeFlags.Union) {
9885- if (intersectUnionsOfPrimitiveTypes(typeSet)) {
9886- // When the intersection creates a reduced set (which might mean that *all* union types have
9887- // disappeared), we restart the operation to get a new set of combined flags. Once we have
9888- // reduced we'll never reduce again, so this occurs at most once.
9889- return getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
9890- }
9891- // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
9892- // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
9893- const unionIndex = findIndex(typeSet, t => (t.flags & TypeFlags.Union) !== 0);
9894- const unionType = <UnionType>typeSet[unionIndex];
9895- return getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
9896- UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
9897- }
98989893 const id = getTypeListId(typeSet);
9899- let type = intersectionTypes.get(id);
9900- if (!type) {
9901- type = <IntersectionType>createType(TypeFlags.Intersection);
9902- intersectionTypes.set(id, type);
9903- type.objectFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable);
9904- type.types = typeSet;
9905- type.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`.
9906- type.aliasTypeArguments = aliasTypeArguments;
9894+ let result = intersectionTypes.get(id);
9895+ if (!result) {
9896+ if (includes & TypeFlags.Union) {
9897+ if (intersectUnionsOfPrimitiveTypes(typeSet)) {
9898+ // When the intersection creates a reduced set (which might mean that *all* union types have
9899+ // disappeared), we restart the operation to get a new set of combined flags. Once we have
9900+ // reduced we'll never reduce again, so this occurs at most once.
9901+ result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
9902+ }
9903+ else {
9904+ // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
9905+ // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
9906+ const unionIndex = findIndex(typeSet, t => (t.flags & TypeFlags.Union) !== 0);
9907+ const unionType = <UnionType>typeSet[unionIndex];
9908+ result = getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
9909+ UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
9910+ }
9911+ }
9912+ else {
9913+ result = createIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
9914+ }
9915+ intersectionTypes.set(id, result);
99079916 }
9908- return type ;
9917+ return result ;
99099918 }
99109919
99119920 function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
0 commit comments