diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a6f0d6dd2166a..d5a110b3ca6bb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12887,65 +12887,82 @@ namespace ts { } function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined): Type { - const checkType = instantiateType(root.checkType, mapper); - const extendsType = instantiateType(root.extendsType, mapper); - if (checkType === wildcardType || extendsType === wildcardType) { - return wildcardType; + let result; + let extraTypes: Type[] | undefined; + // We loop here for an immediately nested conditional type in the false position, effectively treating + // types of the form 'A extends B ? X : C extends D ? Y : E extends F ? Z : ...' as a single construct for + // purposes of resolution. This means such types aren't subject to the instatiation depth limiter. + while (true) { + const checkType = instantiateType(root.checkType, mapper); + const checkTypeInstantiable = isGenericObjectType(checkType) || isGenericIndexType(checkType); + const extendsType = instantiateType(root.extendsType, mapper); + if (checkType === wildcardType || extendsType === wildcardType) { + return wildcardType; + } + let combinedMapper: TypeMapper | undefined; + if (root.inferTypeParameters) { + const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None); + // We skip inference of the possible `infer` types unles the `extendsType` _is_ an infer type + // if it was, it's trivial to say that extendsType = checkType, however such a pattern is used to + // "reset" the type being build up during constraint calculation and avoid making an apparently "infinite" constraint + // so in those cases we refain from performing inference and retain the uninfered type parameter + if (!checkTypeInstantiable || !some(root.inferTypeParameters, t => t === extendsType)) { + // We don't want inferences from constraints as they may cause us to eagerly resolve the + // conditional type instead of deferring resolution. Also, we always want strict function + // types rules (i.e. proper contravariance) for inferences. + inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict); + } + combinedMapper = mergeTypeMappers(mapper, context.mapper); + } + // Instantiate the extends type including inferences for 'infer T' type parameters + const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType; + // We attempt to resolve the conditional type only when the check and extends types are non-generic + if (!checkTypeInstantiable && !isGenericObjectType(inferredExtendsType) && !isGenericIndexType(inferredExtendsType)) { + // Return falseType for a definitely false extends check. We check an instantiations of the two + // types with type parameters mapped to the wildcard type, the most permissive instantiations + // possible (the wildcard type is assignable to and from all types). If those are not related, + // then no instantiations will be and we can just return the false branch type. + if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && (checkType.flags & TypeFlags.Any || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) { + // Return union of trueType and falseType for 'any' since it matches anything + if (checkType.flags & TypeFlags.Any) { + (extraTypes || (extraTypes = [])).push(instantiateTypeWithoutDepthIncrease(root.trueType, combinedMapper || mapper)); + } + // If falseType is an immediately nested conditional type that isn't distributive or has an + // identical checkType, switch to that type and loop. + const falseType = root.falseType; + if (falseType.flags & TypeFlags.Conditional) { + const newRoot = (falseType).root; + if (newRoot.node.parent === root.node && (!newRoot.isDistributive || newRoot.checkType === root.checkType)) { + root = newRoot; + continue; + } + } + result = instantiateTypeWithoutDepthIncrease(falseType, mapper); + break; + } + // Return trueType for a definitely true extends check. We check instantiations of the two + // types with type parameters mapped to their restrictive form, i.e. a form of the type parameter + // that has no constraint. This ensures that, for example, the type + // type Foo = T extends { x: string } ? string : number + // doesn't immediately resolve to 'string' instead of being deferred. + if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) { + result = instantiateTypeWithoutDepthIncrease(root.trueType, combinedMapper || mapper); + break; + } + } + // Return a deferred type for a check that is neither definitely true nor definitely false + const erasedCheckType = getActualTypeVariable(checkType); + result = createType(TypeFlags.Conditional); + result.root = root; + result.checkType = erasedCheckType; + result.extendsType = extendsType; + result.mapper = mapper; + result.combinedMapper = combinedMapper; + result.aliasSymbol = root.aliasSymbol; + result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 + break; } - const checkTypeInstantiable = isGenericObjectType(checkType) || isGenericIndexType(checkType); - let combinedMapper: TypeMapper | undefined; - if (root.inferTypeParameters) { - const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None); - // We skip inference of the possible `infer` types unles the `extendsType` _is_ an infer type - // if it was, it's trivial to say that extendsType = checkType, however such a pattern is used to - // "reset" the type being build up during constraint calculation and avoid making an apparently "infinite" constraint - // so in those cases we refain from performing inference and retain the uninfered type parameter - if (!checkTypeInstantiable || !some(root.inferTypeParameters, t => t === extendsType)) { - // We don't want inferences from constraints as they may cause us to eagerly resolve the - // conditional type instead of deferring resolution. Also, we always want strict function - // types rules (i.e. proper contravariance) for inferences. - inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict); - } - combinedMapper = mergeTypeMappers(mapper, context.mapper); - } - // Instantiate the extends type including inferences for 'infer T' type parameters - const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType; - // We attempt to resolve the conditional type only when the check and extends types are non-generic - if (!checkTypeInstantiable && !isGenericObjectType(inferredExtendsType) && !isGenericIndexType(inferredExtendsType)) { - if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown) { - return instantiateType(root.trueType, combinedMapper || mapper); - } - // Return union of trueType and falseType for 'any' since it matches anything - if (checkType.flags & TypeFlags.Any) { - return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]); - } - // Return falseType for a definitely false extends check. We check an instantiations of the two - // types with type parameters mapped to the wildcard type, the most permissive instantiations - // possible (the wildcard type is assignable to and from all types). If those are not related, - // then no instantiations will be and we can just return the false branch type. - if (!isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType))) { - return instantiateType(root.falseType, mapper); - } - // Return trueType for a definitely true extends check. We check instantiations of the two - // types with type parameters mapped to their restrictive form, i.e. a form of the type parameter - // that has no constraint. This ensures that, for example, the type - // type Foo = T extends { x: string } ? string : number - // doesn't immediately resolve to 'string' instead of being deferred. - if (isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) { - return instantiateType(root.trueType, combinedMapper || mapper); - } - } - // Return a deferred type for a check that is neither definitely true nor definitely false - const erasedCheckType = getActualTypeVariable(checkType); - const result = createType(TypeFlags.Conditional); - result.root = root; - result.checkType = erasedCheckType; - result.extendsType = extendsType; - result.mapper = mapper; - result.combinedMapper = combinedMapper; - result.aliasSymbol = root.aliasSymbol; - result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 - return result; + return extraTypes ? getUnionType(append(extraTypes, result)) : result; } function getTrueTypeFromConditionalType(type: ConditionalType) { @@ -13923,6 +13940,17 @@ namespace ts { return result; } + /** + * This can be used to avoid the penalty on instantiation depth for types which result from immediate + * simplification. It essentially removes the depth increase done in `instantiateType`. + */ + function instantiateTypeWithoutDepthIncrease(type: Type, mapper: TypeMapper | undefined) { + instantiationDepth--; + const result = instantiateType(type, mapper); + instantiationDepth++; + return result; + } + function instantiateTypeWorker(type: Type, mapper: TypeMapper): Type { const flags = type.flags; if (flags & TypeFlags.TypeParameter) { diff --git a/tests/baselines/reference/deeplyNestedConditionalTypes.js b/tests/baselines/reference/deeplyNestedConditionalTypes.js new file mode 100644 index 0000000000000..20199c3a6b634 --- /dev/null +++ b/tests/baselines/reference/deeplyNestedConditionalTypes.js @@ -0,0 +1,116 @@ +//// [deeplyNestedConditionalTypes.ts] +type Foo = + T extends 0 ? '0' : + T extends 1 ? '1' : + T extends 2 ? '2' : + T extends 3 ? '3' : + T extends 4 ? '4' : + T extends 5 ? '5' : + T extends 6 ? '6' : + T extends 7 ? '7' : + T extends 8 ? '8' : + T extends 9 ? '9' : + T extends 10 ? '10' : + T extends 11 ? '11' : + T extends 12 ? '12' : + T extends 13 ? '13' : + T extends 14 ? '14' : + T extends 15 ? '15' : + T extends 16 ? '16' : + T extends 17 ? '17' : + T extends 18 ? '18' : + T extends 19 ? '19' : + T extends 20 ? '20' : + T extends 21 ? '21' : + T extends 22 ? '22' : + T extends 23 ? '23' : + T extends 24 ? '24' : + T extends 25 ? '25' : + T extends 26 ? '26' : + T extends 27 ? '27' : + T extends 28 ? '28' : + T extends 29 ? '29' : + T extends 30 ? '30' : + T extends 31 ? '31' : + T extends 32 ? '32' : + T extends 33 ? '33' : + T extends 34 ? '34' : + T extends 35 ? '35' : + T extends 36 ? '36' : + T extends 37 ? '37' : + T extends 38 ? '38' : + T extends 39 ? '39' : + T extends 40 ? '40' : + T extends 41 ? '41' : + T extends 42 ? '42' : + T extends 43 ? '43' : + T extends 44 ? '44' : + T extends 45 ? '45' : + T extends 46 ? '46' : + T extends 47 ? '47' : + T extends 48 ? '48' : + T extends 49 ? '49' : + T extends 50 ? '50' : + T extends 51 ? '51' : + T extends 52 ? '52' : + T extends 53 ? '53' : + T extends 54 ? '54' : + T extends 55 ? '55' : + T extends 56 ? '56' : + T extends 57 ? '57' : + T extends 58 ? '58' : + T extends 59 ? '59' : + T extends 60 ? '60' : + T extends 61 ? '61' : + T extends 62 ? '62' : + T extends 63 ? '63' : + T extends 64 ? '64' : + T extends 65 ? '65' : + T extends 66 ? '66' : + T extends 67 ? '67' : + T extends 68 ? '68' : + T extends 69 ? '69' : + T extends 70 ? '70' : + T extends 71 ? '71' : + T extends 72 ? '72' : + T extends 73 ? '73' : + T extends 74 ? '74' : + T extends 75 ? '75' : + T extends 76 ? '76' : + T extends 77 ? '77' : + T extends 78 ? '78' : + T extends 79 ? '79' : + T extends 80 ? '80' : + T extends 81 ? '81' : + T extends 82 ? '82' : + T extends 83 ? '83' : + T extends 84 ? '84' : + T extends 85 ? '85' : + T extends 86 ? '86' : + T extends 87 ? '87' : + T extends 88 ? '88' : + T extends 89 ? '89' : + T extends 90 ? '90' : + T extends 91 ? '91' : + T extends 92 ? '92' : + T extends 93 ? '93' : + T extends 94 ? '94' : + T extends 95 ? '95' : + T extends 96 ? '96' : + T extends 97 ? '97' : + T extends 98 ? '98' : + T extends 99 ? '99' : + never; + +type T0 = Foo<99>; +type T1 = Foo; + + +//// [deeplyNestedConditionalTypes.js] +"use strict"; + + +//// [deeplyNestedConditionalTypes.d.ts] +declare type Foo = T extends 0 ? '0' : T extends 1 ? '1' : T extends 2 ? '2' : T extends 3 ? '3' : T extends 4 ? '4' : T extends 5 ? '5' : T extends 6 ? '6' : T extends 7 ? '7' : T extends 8 ? '8' : T extends 9 ? '9' : T extends 10 ? '10' : T extends 11 ? '11' : T extends 12 ? '12' : T extends 13 ? '13' : T extends 14 ? '14' : T extends 15 ? '15' : T extends 16 ? '16' : T extends 17 ? '17' : T extends 18 ? '18' : T extends 19 ? '19' : T extends 20 ? '20' : T extends 21 ? '21' : T extends 22 ? '22' : T extends 23 ? '23' : T extends 24 ? '24' : T extends 25 ? '25' : T extends 26 ? '26' : T extends 27 ? '27' : T extends 28 ? '28' : T extends 29 ? '29' : T extends 30 ? '30' : T extends 31 ? '31' : T extends 32 ? '32' : T extends 33 ? '33' : T extends 34 ? '34' : T extends 35 ? '35' : T extends 36 ? '36' : T extends 37 ? '37' : T extends 38 ? '38' : T extends 39 ? '39' : T extends 40 ? '40' : T extends 41 ? '41' : T extends 42 ? '42' : T extends 43 ? '43' : T extends 44 ? '44' : T extends 45 ? '45' : T extends 46 ? '46' : T extends 47 ? '47' : T extends 48 ? '48' : T extends 49 ? '49' : T extends 50 ? '50' : T extends 51 ? '51' : T extends 52 ? '52' : T extends 53 ? '53' : T extends 54 ? '54' : T extends 55 ? '55' : T extends 56 ? '56' : T extends 57 ? '57' : T extends 58 ? '58' : T extends 59 ? '59' : T extends 60 ? '60' : T extends 61 ? '61' : T extends 62 ? '62' : T extends 63 ? '63' : T extends 64 ? '64' : T extends 65 ? '65' : T extends 66 ? '66' : T extends 67 ? '67' : T extends 68 ? '68' : T extends 69 ? '69' : T extends 70 ? '70' : T extends 71 ? '71' : T extends 72 ? '72' : T extends 73 ? '73' : T extends 74 ? '74' : T extends 75 ? '75' : T extends 76 ? '76' : T extends 77 ? '77' : T extends 78 ? '78' : T extends 79 ? '79' : T extends 80 ? '80' : T extends 81 ? '81' : T extends 82 ? '82' : T extends 83 ? '83' : T extends 84 ? '84' : T extends 85 ? '85' : T extends 86 ? '86' : T extends 87 ? '87' : T extends 88 ? '88' : T extends 89 ? '89' : T extends 90 ? '90' : T extends 91 ? '91' : T extends 92 ? '92' : T extends 93 ? '93' : T extends 94 ? '94' : T extends 95 ? '95' : T extends 96 ? '96' : T extends 97 ? '97' : T extends 98 ? '98' : T extends 99 ? '99' : never; +declare type T0 = Foo<99>; +declare type T1 = Foo; diff --git a/tests/baselines/reference/deeplyNestedConditionalTypes.symbols b/tests/baselines/reference/deeplyNestedConditionalTypes.symbols new file mode 100644 index 0000000000000..2ed77ae471a4c --- /dev/null +++ b/tests/baselines/reference/deeplyNestedConditionalTypes.symbols @@ -0,0 +1,315 @@ +=== tests/cases/compiler/deeplyNestedConditionalTypes.ts === +type Foo = +>Foo : Symbol(Foo, Decl(deeplyNestedConditionalTypes.ts, 0, 0)) +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 0 ? '0' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 1 ? '1' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 2 ? '2' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 3 ? '3' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 4 ? '4' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 5 ? '5' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 6 ? '6' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 7 ? '7' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 8 ? '8' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 9 ? '9' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 10 ? '10' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 11 ? '11' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 12 ? '12' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 13 ? '13' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 14 ? '14' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 15 ? '15' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 16 ? '16' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 17 ? '17' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 18 ? '18' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 19 ? '19' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 20 ? '20' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 21 ? '21' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 22 ? '22' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 23 ? '23' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 24 ? '24' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 25 ? '25' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 26 ? '26' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 27 ? '27' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 28 ? '28' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 29 ? '29' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 30 ? '30' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 31 ? '31' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 32 ? '32' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 33 ? '33' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 34 ? '34' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 35 ? '35' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 36 ? '36' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 37 ? '37' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 38 ? '38' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 39 ? '39' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 40 ? '40' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 41 ? '41' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 42 ? '42' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 43 ? '43' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 44 ? '44' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 45 ? '45' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 46 ? '46' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 47 ? '47' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 48 ? '48' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 49 ? '49' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 50 ? '50' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 51 ? '51' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 52 ? '52' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 53 ? '53' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 54 ? '54' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 55 ? '55' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 56 ? '56' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 57 ? '57' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 58 ? '58' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 59 ? '59' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 60 ? '60' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 61 ? '61' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 62 ? '62' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 63 ? '63' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 64 ? '64' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 65 ? '65' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 66 ? '66' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 67 ? '67' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 68 ? '68' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 69 ? '69' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 70 ? '70' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 71 ? '71' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 72 ? '72' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 73 ? '73' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 74 ? '74' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 75 ? '75' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 76 ? '76' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 77 ? '77' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 78 ? '78' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 79 ? '79' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 80 ? '80' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 81 ? '81' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 82 ? '82' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 83 ? '83' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 84 ? '84' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 85 ? '85' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 86 ? '86' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 87 ? '87' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 88 ? '88' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 89 ? '89' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 90 ? '90' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 91 ? '91' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 92 ? '92' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 93 ? '93' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 94 ? '94' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 95 ? '95' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 96 ? '96' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 97 ? '97' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 98 ? '98' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + T extends 99 ? '99' : +>T : Symbol(T, Decl(deeplyNestedConditionalTypes.ts, 0, 9)) + + never; + +type T0 = Foo<99>; +>T0 : Symbol(T0, Decl(deeplyNestedConditionalTypes.ts, 101, 10)) +>Foo : Symbol(Foo, Decl(deeplyNestedConditionalTypes.ts, 0, 0)) + +type T1 = Foo; +>T1 : Symbol(T1, Decl(deeplyNestedConditionalTypes.ts, 103, 18)) +>Foo : Symbol(Foo, Decl(deeplyNestedConditionalTypes.ts, 0, 0)) + diff --git a/tests/baselines/reference/deeplyNestedConditionalTypes.types b/tests/baselines/reference/deeplyNestedConditionalTypes.types new file mode 100644 index 0000000000000..d233e86bbbb86 --- /dev/null +++ b/tests/baselines/reference/deeplyNestedConditionalTypes.types @@ -0,0 +1,112 @@ +=== tests/cases/compiler/deeplyNestedConditionalTypes.ts === +type Foo = +>Foo : Foo + + T extends 0 ? '0' : + T extends 1 ? '1' : + T extends 2 ? '2' : + T extends 3 ? '3' : + T extends 4 ? '4' : + T extends 5 ? '5' : + T extends 6 ? '6' : + T extends 7 ? '7' : + T extends 8 ? '8' : + T extends 9 ? '9' : + T extends 10 ? '10' : + T extends 11 ? '11' : + T extends 12 ? '12' : + T extends 13 ? '13' : + T extends 14 ? '14' : + T extends 15 ? '15' : + T extends 16 ? '16' : + T extends 17 ? '17' : + T extends 18 ? '18' : + T extends 19 ? '19' : + T extends 20 ? '20' : + T extends 21 ? '21' : + T extends 22 ? '22' : + T extends 23 ? '23' : + T extends 24 ? '24' : + T extends 25 ? '25' : + T extends 26 ? '26' : + T extends 27 ? '27' : + T extends 28 ? '28' : + T extends 29 ? '29' : + T extends 30 ? '30' : + T extends 31 ? '31' : + T extends 32 ? '32' : + T extends 33 ? '33' : + T extends 34 ? '34' : + T extends 35 ? '35' : + T extends 36 ? '36' : + T extends 37 ? '37' : + T extends 38 ? '38' : + T extends 39 ? '39' : + T extends 40 ? '40' : + T extends 41 ? '41' : + T extends 42 ? '42' : + T extends 43 ? '43' : + T extends 44 ? '44' : + T extends 45 ? '45' : + T extends 46 ? '46' : + T extends 47 ? '47' : + T extends 48 ? '48' : + T extends 49 ? '49' : + T extends 50 ? '50' : + T extends 51 ? '51' : + T extends 52 ? '52' : + T extends 53 ? '53' : + T extends 54 ? '54' : + T extends 55 ? '55' : + T extends 56 ? '56' : + T extends 57 ? '57' : + T extends 58 ? '58' : + T extends 59 ? '59' : + T extends 60 ? '60' : + T extends 61 ? '61' : + T extends 62 ? '62' : + T extends 63 ? '63' : + T extends 64 ? '64' : + T extends 65 ? '65' : + T extends 66 ? '66' : + T extends 67 ? '67' : + T extends 68 ? '68' : + T extends 69 ? '69' : + T extends 70 ? '70' : + T extends 71 ? '71' : + T extends 72 ? '72' : + T extends 73 ? '73' : + T extends 74 ? '74' : + T extends 75 ? '75' : + T extends 76 ? '76' : + T extends 77 ? '77' : + T extends 78 ? '78' : + T extends 79 ? '79' : + T extends 80 ? '80' : + T extends 81 ? '81' : + T extends 82 ? '82' : + T extends 83 ? '83' : + T extends 84 ? '84' : + T extends 85 ? '85' : + T extends 86 ? '86' : + T extends 87 ? '87' : + T extends 88 ? '88' : + T extends 89 ? '89' : + T extends 90 ? '90' : + T extends 91 ? '91' : + T extends 92 ? '92' : + T extends 93 ? '93' : + T extends 94 ? '94' : + T extends 95 ? '95' : + T extends 96 ? '96' : + T extends 97 ? '97' : + T extends 98 ? '98' : + T extends 99 ? '99' : + never; + +type T0 = Foo<99>; +>T0 : "99" + +type T1 = Foo; +>T1 : "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16" | "17" | "18" | "19" | "20" | "21" | "22" | "23" | "24" | "25" | "26" | "27" | "28" | "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36" | "37" | "38" | "39" | "40" | "41" | "42" | "43" | "44" | "45" | "46" | "47" | "48" | "49" | "50" | "51" | "52" | "53" | "54" | "55" | "56" | "57" | "58" | "59" | "60" | "61" | "62" | "63" | "64" | "65" | "66" | "67" | "68" | "69" | "70" | "71" | "72" | "73" | "74" | "75" | "76" | "77" | "78" | "79" | "80" | "81" | "82" | "83" | "84" | "85" | "86" | "87" | "88" | "89" | "90" | "91" | "92" | "93" | "94" | "95" | "96" | "97" | "98" | "99" + diff --git a/tests/cases/compiler/deeplyNestedConditionalTypes.ts b/tests/cases/compiler/deeplyNestedConditionalTypes.ts new file mode 100644 index 0000000000000..9923f2ce4153c --- /dev/null +++ b/tests/cases/compiler/deeplyNestedConditionalTypes.ts @@ -0,0 +1,108 @@ +// @strict: true +// @declaration: true + +type Foo = + T extends 0 ? '0' : + T extends 1 ? '1' : + T extends 2 ? '2' : + T extends 3 ? '3' : + T extends 4 ? '4' : + T extends 5 ? '5' : + T extends 6 ? '6' : + T extends 7 ? '7' : + T extends 8 ? '8' : + T extends 9 ? '9' : + T extends 10 ? '10' : + T extends 11 ? '11' : + T extends 12 ? '12' : + T extends 13 ? '13' : + T extends 14 ? '14' : + T extends 15 ? '15' : + T extends 16 ? '16' : + T extends 17 ? '17' : + T extends 18 ? '18' : + T extends 19 ? '19' : + T extends 20 ? '20' : + T extends 21 ? '21' : + T extends 22 ? '22' : + T extends 23 ? '23' : + T extends 24 ? '24' : + T extends 25 ? '25' : + T extends 26 ? '26' : + T extends 27 ? '27' : + T extends 28 ? '28' : + T extends 29 ? '29' : + T extends 30 ? '30' : + T extends 31 ? '31' : + T extends 32 ? '32' : + T extends 33 ? '33' : + T extends 34 ? '34' : + T extends 35 ? '35' : + T extends 36 ? '36' : + T extends 37 ? '37' : + T extends 38 ? '38' : + T extends 39 ? '39' : + T extends 40 ? '40' : + T extends 41 ? '41' : + T extends 42 ? '42' : + T extends 43 ? '43' : + T extends 44 ? '44' : + T extends 45 ? '45' : + T extends 46 ? '46' : + T extends 47 ? '47' : + T extends 48 ? '48' : + T extends 49 ? '49' : + T extends 50 ? '50' : + T extends 51 ? '51' : + T extends 52 ? '52' : + T extends 53 ? '53' : + T extends 54 ? '54' : + T extends 55 ? '55' : + T extends 56 ? '56' : + T extends 57 ? '57' : + T extends 58 ? '58' : + T extends 59 ? '59' : + T extends 60 ? '60' : + T extends 61 ? '61' : + T extends 62 ? '62' : + T extends 63 ? '63' : + T extends 64 ? '64' : + T extends 65 ? '65' : + T extends 66 ? '66' : + T extends 67 ? '67' : + T extends 68 ? '68' : + T extends 69 ? '69' : + T extends 70 ? '70' : + T extends 71 ? '71' : + T extends 72 ? '72' : + T extends 73 ? '73' : + T extends 74 ? '74' : + T extends 75 ? '75' : + T extends 76 ? '76' : + T extends 77 ? '77' : + T extends 78 ? '78' : + T extends 79 ? '79' : + T extends 80 ? '80' : + T extends 81 ? '81' : + T extends 82 ? '82' : + T extends 83 ? '83' : + T extends 84 ? '84' : + T extends 85 ? '85' : + T extends 86 ? '86' : + T extends 87 ? '87' : + T extends 88 ? '88' : + T extends 89 ? '89' : + T extends 90 ? '90' : + T extends 91 ? '91' : + T extends 92 ? '92' : + T extends 93 ? '93' : + T extends 94 ? '94' : + T extends 95 ? '95' : + T extends 96 ? '96' : + T extends 97 ? '97' : + T extends 98 ? '98' : + T extends 99 ? '99' : + never; + +type T0 = Foo<99>; +type T1 = Foo;