@@ -16227,28 +16227,21 @@ namespace ts {
16227
16227
let result = root.instantiations!.get(id);
16228
16228
if (!result) {
16229
16229
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
16230
- result = instantiateConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
16230
+ const checkType = root.checkType;
16231
+ const distributionType = root.isDistributive ? getMappedType(checkType, newMapper) : undefined;
16232
+ // Distributive conditional types are distributed over union types. For example, when the
16233
+ // distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
16234
+ // result is (A extends U ? X : Y) | (B extends U ? X : Y).
16235
+ result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
16236
+ mapTypeWithAlias(distributionType, t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) :
16237
+ getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
16231
16238
root.instantiations!.set(id, result);
16232
16239
}
16233
16240
return result;
16234
16241
}
16235
16242
return type;
16236
16243
}
16237
16244
16238
- function instantiateConditionalType(root: ConditionalRoot, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
16239
- // Check if we have a conditional type where the check type is a naked type parameter. If so,
16240
- // the conditional type is distributive over union types and when T is instantiated to a union
16241
- // type A | B, we produce (A extends U ? X : Y) | (B extends U ? X : Y).
16242
- if (root.isDistributive) {
16243
- const checkType = root.checkType as TypeParameter;
16244
- const instantiatedType = getMappedType(checkType, mapper);
16245
- if (checkType !== instantiatedType && instantiatedType.flags & (TypeFlags.Union | TypeFlags.Never)) {
16246
- return mapTypeWithAlias(instantiatedType, t => getConditionalType(root, prependTypeMapping(checkType, t, mapper)), aliasSymbol, aliasTypeArguments);
16247
- }
16248
- }
16249
- return getConditionalType(root, mapper, aliasSymbol, aliasTypeArguments);
16250
- }
16251
-
16252
16245
function instantiateType(type: Type, mapper: TypeMapper | undefined): Type;
16253
16246
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined;
16254
16247
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {
@@ -16259,10 +16252,10 @@ namespace ts {
16259
16252
if (!couldContainTypeVariables(type)) {
16260
16253
return type;
16261
16254
}
16262
- if (instantiationDepth === 50 || instantiationCount >= 5000000) {
16263
- // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
16264
- // with a combination of infinite generic types that perpetually generate new type identities. We stop
16265
- // the recursion here by yielding the error type.
16255
+ if (instantiationDepth === 500 || instantiationCount >= 5000000) {
16256
+ // We have reached 500 recursive type instantiations, or 5M type instantiations caused by the same statement
16257
+ // or expression. There is a very high likelyhood we're dealing with a combination of infinite generic types
16258
+ // that perpetually generate new type identities, so we stop the recursion here by yielding the error type.
16266
16259
tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount });
16267
16260
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
16268
16261
return errorType;
0 commit comments