@@ -16257,19 +16257,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16257
16257
// Add the given types to the given type set. Order is preserved, duplicates are removed,
16258
16258
// and nested types of the given kind are flattened into the set.
16259
16259
function addTypesToUnion(typeSet: Type[], includes: TypeFlags, types: readonly Type[]): TypeFlags {
16260
- let lastUnion : Type | undefined;
16260
+ let lastType : Type | undefined;
16261
16261
for (const type of types) {
16262
- if (type.flags & TypeFlags.Union) {
16263
- // We skip the union type if it is the same as the last union we processed. We could potentially track
16264
- // all union types that we've processed, but this simple test is fast and covers the scenarios we care
16265
- // about (in particular, Record<A, B>[A], where A and B are large union types).
16266
- if (type !== lastUnion) {
16267
- includes = addTypesToUnion(typeSet, includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), (type as UnionType).types);
16268
- lastUnion = type;
16269
- }
16270
- }
16271
- else {
16272
- includes = addTypeToUnion(typeSet, includes, type);
16262
+ // We skip the type if it is the same as the last type we processed. This simple test particularly
16263
+ // saves a lot of work for large lists of the same union type, such as when resolving `Record<A, B>[A]`,
16264
+ // where A and B are large union types.
16265
+ if (type !== lastType) {
16266
+ includes = type.flags & TypeFlags.Union ?
16267
+ addTypesToUnion(typeSet, includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), (type as UnionType).types) :
16268
+ addTypeToUnion(typeSet, includes, type);
16269
+ lastType = type;
16273
16270
}
16274
16271
}
16275
16272
return includes;
@@ -16425,7 +16422,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16425
16422
// We optimize for the common case of unioning a union type with some other type (such as `undefined`).
16426
16423
if (types.length === 2 && !origin && (types[0].flags & TypeFlags.Union || types[1].flags & TypeFlags.Union)) {
16427
16424
const infix = unionReduction === UnionReduction.None ? "N" : unionReduction === UnionReduction.Subtype ? "S" : "L";
16428
- const id = types[0].id + infix + types[1].id + getAliasId(aliasSymbol, aliasTypeArguments);
16425
+ const index = types[0].id < types[1].id ? 0 : 1;
16426
+ const id = types[index].id + infix + types[1 - index].id + getAliasId(aliasSymbol, aliasTypeArguments);
16429
16427
let type = unionOfUnionTypes.get(id);
16430
16428
if (!type) {
16431
16429
type = getUnionTypeWorker(types, unionReduction, aliasSymbol, aliasTypeArguments, origin);
0 commit comments