diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a619238c90fdc..8466e06dde2b4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17668,9 +17668,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function removeStringLiteralsMatchedByTemplateLiterals(types: Type[]) { + function removeStringLiteralsMatchedByTemplateLiterals(types: Type[]): Type[] | undefined { const templates = filter(types, isPatternLiteralType) as (TemplateLiteralType | StringMappingType)[]; if (templates.length) { + const estimatedCount = templates.length * countWhere(types, t => !!(t.flags & TypeFlags.StringLiteral)); + if (estimatedCount > 1000000) { + tracing?.instant(tracing.Phase.CheckTypes, "removeStringLiteralsMatchedByTemplateLiterals_DepthLimit", { typeIds: types.map(t => t.id) }); + error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); + return undefined; + } + let i = types.length; while (i > 0) { i--; @@ -17680,6 +17687,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } + return types; } function isTypeMatchedByTemplateLiteralOrStringMapping(type: Type, template: TemplateLiteralType | StringMappingType) { @@ -17804,7 +17812,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & UnionReduction.Subtype)); } if (includes & TypeFlags.StringLiteral && includes & (TypeFlags.TemplateLiteral | TypeFlags.StringMapping)) { - removeStringLiteralsMatchedByTemplateLiterals(typeSet); + typeSet = removeStringLiteralsMatchedByTemplateLiterals(typeSet); + if (!typeSet) { + return errorType; + } } if (includes & TypeFlags.IncludesConstrainedTypeVariable) { removeConstrainedTypeVariables(typeSet); diff --git a/tests/baselines/reference/templateLiteralTypes1.errors.txt b/tests/baselines/reference/templateLiteralTypes1.errors.txt index ed921a5dbfe66..bfdad709c9c26 100644 --- a/tests/baselines/reference/templateLiteralTypes1.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes1.errors.txt @@ -6,10 +6,11 @@ templateLiteralTypes1.ts(165,15): error TS1338: 'infer' declarations are only pe templateLiteralTypes1.ts(197,16): error TS2590: Expression produces a union type that is too complex to represent. templateLiteralTypes1.ts(201,16): error TS2590: Expression produces a union type that is too complex to represent. templateLiteralTypes1.ts(205,16): error TS2590: Expression produces a union type that is too complex to represent. +templateLiteralTypes1.ts(251,7): error TS2590: Expression produces a union type that is too complex to represent. templateLiteralTypes1.ts(252,7): error TS2590: Expression produces a union type that is too complex to represent. -==== templateLiteralTypes1.ts (7 errors) ==== +==== templateLiteralTypes1.ts (8 errors) ==== // Template types example from #12754 const createScopedActionType = (scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}`; @@ -276,6 +277,8 @@ templateLiteralTypes1.ts(252,7): error TS2590: Expression produces a union type export type SpacingShorthand = | `${Spacing} ${Spacing}` | `${Spacing} ${Spacing} ${Spacing}` + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2590: Expression produces a union type that is too complex to represent. | `${Spacing} ${Spacing} ${Spacing} ${Spacing}`; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2590: Expression produces a union type that is too complex to represent.