From eee799fe0cf52ced3acec1e3a0423dc3c4c733ea Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 11 Sep 2020 14:48:35 -1000 Subject: [PATCH] Properly check types in template literal placeholders (#40498) * Properly check types in template literal placeholders * Add regression test * Update test * Accept new baselines --- src/compiler/checker.ts | 8 +- .../templateLiteralTypes1.errors.txt | 17 +- .../reference/templateLiteralTypes1.js | 13 +- .../reference/templateLiteralTypes1.symbols | 346 +++++++++--------- .../reference/templateLiteralTypes1.types | 11 +- .../types/literal/templateLiteralTypes1.ts | 10 +- 6 files changed, 216 insertions(+), 189 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 14432d76894..e21e46126f4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31548,16 +31548,16 @@ namespace ts { registerForUnusedIdentifiersCheck(node); } - function checkTemplateType(node: TemplateLiteralTypeNode) { - forEachChild(node, checkSourceElement); - getTypeFromTypeNode(node); + function checkTemplateLiteralType(node: TemplateLiteralTypeNode) { for (const span of node.templateSpans) { + checkSourceElement(span.type); const type = getTypeFromTypeNode(span.type); checkTypeAssignableTo(type, templateConstraintType, span.type); if (!everyType(type, t => !!(t.flags & TypeFlags.Literal) || isGenericIndexType(t))) { error(span.type, Diagnostics.Template_literal_type_argument_0_is_not_literal_type_or_a_generic_type, typeToString(type)); } } + getTypeFromTypeNode(node); } function checkImportType(node: ImportTypeNode) { @@ -36198,7 +36198,7 @@ namespace ts { case SyntaxKind.InferType: return checkInferType(node); case SyntaxKind.TemplateLiteralType: - return checkTemplateType(node); + return checkTemplateLiteralType(node); case SyntaxKind.ImportType: return checkImportType(node); case SyntaxKind.NamedTupleMember: diff --git a/tests/baselines/reference/templateLiteralTypes1.errors.txt b/tests/baselines/reference/templateLiteralTypes1.errors.txt index 055bb929a98..e4b8aa2920b 100644 --- a/tests/baselines/reference/templateLiteralTypes1.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes1.errors.txt @@ -4,12 +4,13 @@ tests/cases/conformance/types/literal/templateLiteralTypes1.ts(39,5): error TS23 'A' is assignable to the constraint of type 'B', but 'B' could be instantiated with a different subtype of constraint 'string'. Type 'string' is not assignable to type 'B'. 'string' is assignable to the constraint of type 'B', but 'B' could be instantiated with a different subtype of constraint 'string'. -tests/cases/conformance/types/literal/templateLiteralTypes1.ts(184,16): error TS2590: Expression produces a union type that is too complex to represent. +tests/cases/conformance/types/literal/templateLiteralTypes1.ts(165,15): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. tests/cases/conformance/types/literal/templateLiteralTypes1.ts(188,16): error TS2590: Expression produces a union type that is too complex to represent. tests/cases/conformance/types/literal/templateLiteralTypes1.ts(192,16): error TS2590: Expression produces a union type that is too complex to represent. +tests/cases/conformance/types/literal/templateLiteralTypes1.ts(196,16): error TS2590: Expression produces a union type that is too complex to represent. -==== tests/cases/conformance/types/literal/templateLiteralTypes1.ts (5 errors) ==== +==== tests/cases/conformance/types/literal/templateLiteralTypes1.ts (6 errors) ==== // Template types example from #12754 const createScopedActionType = (scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}`; @@ -61,10 +62,10 @@ tests/cases/conformance/types/literal/templateLiteralTypes1.ts(192,16): error TS // String transformations using recursive conditional types - type Join = + type Join = T extends [] ? '' : - T extends [unknown] ? `${T[0]}` : - T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + T extends [string | number | boolean | bigint] ? `${T[0]}` : + T extends [string | number | boolean | bigint, ...infer U] ? `${T[0]}${D}${Join}` : string; type TJ1 = Join<[1, 2, 3, 4], '.'> @@ -180,6 +181,12 @@ tests/cases/conformance/types/literal/templateLiteralTypes1.ts(192,16): error TS type S1 = T extends `foo${infer U}bar` ? S2 : never; type S2 = S; + // Check that infer T declarations are validated + + type TV1 = `${infer X}`; + ~~~~~~~ +!!! error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type. + // Batched single character inferences for lower recursion depth type Chars = diff --git a/tests/baselines/reference/templateLiteralTypes1.js b/tests/baselines/reference/templateLiteralTypes1.js index c056b9bc1e7..fb782891d04 100644 --- a/tests/baselines/reference/templateLiteralTypes1.js +++ b/tests/baselines/reference/templateLiteralTypes1.js @@ -42,10 +42,10 @@ function fa2(x: { [P in B as `p_$ // String transformations using recursive conditional types -type Join = +type Join = T extends [] ? '' : - T extends [unknown] ? `${T[0]}` : - T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + T extends [string | number | boolean | bigint] ? `${T[0]}` : + T extends [string | number | boolean | bigint, ...infer U] ? `${T[0]}${D}${Join}` : string; type TJ1 = Join<[1, 2, 3, 4], '.'> @@ -161,6 +161,10 @@ getPropValue(obj, s); // unknown type S1 = T extends `foo${infer U}bar` ? S2 : never; type S2 = S; +// Check that infer T declarations are validated + +type TV1 = `${infer X}`; + // Batched single character inferences for lower recursion depth type Chars = @@ -246,7 +250,7 @@ declare function fa2(x: { }, y: { [Q in A as `p_${Q}`]: U; }): void; -declare type Join = T extends [] ? '' : T extends [unknown] ? `${T[0]}` : T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : string; +declare type Join = T extends [] ? '' : T extends [string | number | boolean | bigint] ? `${T[0]}` : T extends [string | number | boolean | bigint, ...infer U] ? `${T[0]}${D}${Join}` : string; declare type TJ1 = Join<[1, 2, 3, 4], '.'>; declare type TJ2 = Join<['foo', 'bar', 'baz'], '-'>; declare type TJ3 = Join<[], '.'>; @@ -322,6 +326,7 @@ declare const obj: { }; declare type S1 = T extends `foo${infer U}bar` ? S2 : never; declare type S2 = S; +declare type TV1 = `${infer X}`; declare type Chars = string extends S ? string[] : S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : S extends `${infer C}${infer R}` ? [C, ...Chars] : S extends '' ? [] : never; declare type L1 = Chars<'FooBarBazThisIsALongerString'>; declare type A = any; diff --git a/tests/baselines/reference/templateLiteralTypes1.symbols b/tests/baselines/reference/templateLiteralTypes1.symbols index ce4fd7e0d34..a39c641d538 100644 --- a/tests/baselines/reference/templateLiteralTypes1.symbols +++ b/tests/baselines/reference/templateLiteralTypes1.symbols @@ -138,26 +138,26 @@ function fa2(x: { [P in B as `p_$ // String transformations using recursive conditional types -type Join = +type Join = >Join : Symbol(Join, Decl(templateLiteralTypes1.ts, 39, 1)) >T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) ->D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 59)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 30)) T extends [] ? '' : >T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) - T extends [unknown] ? `${T[0]}` : + T extends [string | number | boolean | bigint] ? `${T[0]}` : >T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) >T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) - T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + T extends [string | number | boolean | bigint, ...infer U] ? `${T[0]}${D}${Join}` : >T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) ->U : Symbol(U, Decl(templateLiteralTypes1.ts, 46, 32)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 46, 59)) >T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) ->D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 59)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 30)) >Join : Symbol(Join, Decl(templateLiteralTypes1.ts, 39, 1)) ->U : Symbol(U, Decl(templateLiteralTypes1.ts, 46, 32)) ->D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 59)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 46, 59)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 30)) string; @@ -609,205 +609,211 @@ type S2 = S; >S : Symbol(S, Decl(templateLiteralTypes1.ts, 160, 8)) >S : Symbol(S, Decl(templateLiteralTypes1.ts, 160, 8)) +// Check that infer T declarations are validated + +type TV1 = `${infer X}`; +>TV1 : Symbol(TV1, Decl(templateLiteralTypes1.ts, 160, 30)) +>X : Symbol(X, Decl(templateLiteralTypes1.ts, 164, 19)) + // Batched single character inferences for lower recursion depth type Chars = ->Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) ->S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 164, 24)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 168, 11)) string extends S ? string[] : ->S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 168, 11)) S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : ->S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) ->C0 : Symbol(C0, Decl(templateLiteralTypes1.ts, 166, 22)) ->C1 : Symbol(C1, Decl(templateLiteralTypes1.ts, 166, 33)) ->C2 : Symbol(C2, Decl(templateLiteralTypes1.ts, 166, 44)) ->C3 : Symbol(C3, Decl(templateLiteralTypes1.ts, 166, 55)) ->C4 : Symbol(C4, Decl(templateLiteralTypes1.ts, 166, 66)) ->C5 : Symbol(C5, Decl(templateLiteralTypes1.ts, 166, 77)) ->C6 : Symbol(C6, Decl(templateLiteralTypes1.ts, 166, 88)) ->C7 : Symbol(C7, Decl(templateLiteralTypes1.ts, 166, 99)) ->C8 : Symbol(C8, Decl(templateLiteralTypes1.ts, 166, 110)) ->C9 : Symbol(C9, Decl(templateLiteralTypes1.ts, 166, 121)) ->R : Symbol(R, Decl(templateLiteralTypes1.ts, 166, 132)) ->C0 : Symbol(C0, Decl(templateLiteralTypes1.ts, 166, 22)) ->C1 : Symbol(C1, Decl(templateLiteralTypes1.ts, 166, 33)) ->C2 : Symbol(C2, Decl(templateLiteralTypes1.ts, 166, 44)) ->C3 : Symbol(C3, Decl(templateLiteralTypes1.ts, 166, 55)) ->C4 : Symbol(C4, Decl(templateLiteralTypes1.ts, 166, 66)) ->C5 : Symbol(C5, Decl(templateLiteralTypes1.ts, 166, 77)) ->C6 : Symbol(C6, Decl(templateLiteralTypes1.ts, 166, 88)) ->C7 : Symbol(C7, Decl(templateLiteralTypes1.ts, 166, 99)) ->C8 : Symbol(C8, Decl(templateLiteralTypes1.ts, 166, 110)) ->C9 : Symbol(C9, Decl(templateLiteralTypes1.ts, 166, 121)) ->Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) ->R : Symbol(R, Decl(templateLiteralTypes1.ts, 166, 132)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 168, 11)) +>C0 : Symbol(C0, Decl(templateLiteralTypes1.ts, 170, 22)) +>C1 : Symbol(C1, Decl(templateLiteralTypes1.ts, 170, 33)) +>C2 : Symbol(C2, Decl(templateLiteralTypes1.ts, 170, 44)) +>C3 : Symbol(C3, Decl(templateLiteralTypes1.ts, 170, 55)) +>C4 : Symbol(C4, Decl(templateLiteralTypes1.ts, 170, 66)) +>C5 : Symbol(C5, Decl(templateLiteralTypes1.ts, 170, 77)) +>C6 : Symbol(C6, Decl(templateLiteralTypes1.ts, 170, 88)) +>C7 : Symbol(C7, Decl(templateLiteralTypes1.ts, 170, 99)) +>C8 : Symbol(C8, Decl(templateLiteralTypes1.ts, 170, 110)) +>C9 : Symbol(C9, Decl(templateLiteralTypes1.ts, 170, 121)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 170, 132)) +>C0 : Symbol(C0, Decl(templateLiteralTypes1.ts, 170, 22)) +>C1 : Symbol(C1, Decl(templateLiteralTypes1.ts, 170, 33)) +>C2 : Symbol(C2, Decl(templateLiteralTypes1.ts, 170, 44)) +>C3 : Symbol(C3, Decl(templateLiteralTypes1.ts, 170, 55)) +>C4 : Symbol(C4, Decl(templateLiteralTypes1.ts, 170, 66)) +>C5 : Symbol(C5, Decl(templateLiteralTypes1.ts, 170, 77)) +>C6 : Symbol(C6, Decl(templateLiteralTypes1.ts, 170, 88)) +>C7 : Symbol(C7, Decl(templateLiteralTypes1.ts, 170, 99)) +>C8 : Symbol(C8, Decl(templateLiteralTypes1.ts, 170, 110)) +>C9 : Symbol(C9, Decl(templateLiteralTypes1.ts, 170, 121)) +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 164, 24)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 170, 132)) S extends `${infer C}${infer R}` ? [C, ...Chars] : ->S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) ->C : Symbol(C, Decl(templateLiteralTypes1.ts, 167, 22)) ->R : Symbol(R, Decl(templateLiteralTypes1.ts, 167, 32)) ->C : Symbol(C, Decl(templateLiteralTypes1.ts, 167, 22)) ->Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) ->R : Symbol(R, Decl(templateLiteralTypes1.ts, 167, 32)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 168, 11)) +>C : Symbol(C, Decl(templateLiteralTypes1.ts, 171, 22)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 171, 32)) +>C : Symbol(C, Decl(templateLiteralTypes1.ts, 171, 22)) +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 164, 24)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 171, 32)) S extends '' ? [] : ->S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 168, 11)) never; type L1 = Chars<'FooBarBazThisIsALongerString'>; // ['F', 'o', 'o', 'B', 'a', 'r', ...] ->L1 : Symbol(L1, Decl(templateLiteralTypes1.ts, 169, 10)) ->Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) +>L1 : Symbol(L1, Decl(templateLiteralTypes1.ts, 173, 10)) +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 164, 24)) // Cross product unions limited to 100,000 constituents type A = any; ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) type U1 = {a1:A} | {b1:A} | {c1:A} | {d1:A} | {e1:A} | {f1:A} | {g1:A} | {h1:A} | {i1:A} | {j1:A}; ->U1 : Symbol(U1, Decl(templateLiteralTypes1.ts, 175, 13)) ->a1 : Symbol(a1, Decl(templateLiteralTypes1.ts, 177, 11)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->b1 : Symbol(b1, Decl(templateLiteralTypes1.ts, 177, 20)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->c1 : Symbol(c1, Decl(templateLiteralTypes1.ts, 177, 29)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->d1 : Symbol(d1, Decl(templateLiteralTypes1.ts, 177, 38)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->e1 : Symbol(e1, Decl(templateLiteralTypes1.ts, 177, 47)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->f1 : Symbol(f1, Decl(templateLiteralTypes1.ts, 177, 56)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->g1 : Symbol(g1, Decl(templateLiteralTypes1.ts, 177, 65)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->h1 : Symbol(h1, Decl(templateLiteralTypes1.ts, 177, 74)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->i1 : Symbol(i1, Decl(templateLiteralTypes1.ts, 177, 83)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->j1 : Symbol(j1, Decl(templateLiteralTypes1.ts, 177, 92)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>U1 : Symbol(U1, Decl(templateLiteralTypes1.ts, 179, 13)) +>a1 : Symbol(a1, Decl(templateLiteralTypes1.ts, 181, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>b1 : Symbol(b1, Decl(templateLiteralTypes1.ts, 181, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>c1 : Symbol(c1, Decl(templateLiteralTypes1.ts, 181, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>d1 : Symbol(d1, Decl(templateLiteralTypes1.ts, 181, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>e1 : Symbol(e1, Decl(templateLiteralTypes1.ts, 181, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>f1 : Symbol(f1, Decl(templateLiteralTypes1.ts, 181, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>g1 : Symbol(g1, Decl(templateLiteralTypes1.ts, 181, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>h1 : Symbol(h1, Decl(templateLiteralTypes1.ts, 181, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>i1 : Symbol(i1, Decl(templateLiteralTypes1.ts, 181, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>j1 : Symbol(j1, Decl(templateLiteralTypes1.ts, 181, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) type U2 = {a2:A} | {b2:A} | {c2:A} | {d2:A} | {e2:A} | {f2:A} | {g2:A} | {h2:A} | {i2:A} | {j2:A}; ->U2 : Symbol(U2, Decl(templateLiteralTypes1.ts, 177, 98)) ->a2 : Symbol(a2, Decl(templateLiteralTypes1.ts, 178, 11)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->b2 : Symbol(b2, Decl(templateLiteralTypes1.ts, 178, 20)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->c2 : Symbol(c2, Decl(templateLiteralTypes1.ts, 178, 29)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->d2 : Symbol(d2, Decl(templateLiteralTypes1.ts, 178, 38)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->e2 : Symbol(e2, Decl(templateLiteralTypes1.ts, 178, 47)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->f2 : Symbol(f2, Decl(templateLiteralTypes1.ts, 178, 56)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->g2 : Symbol(g2, Decl(templateLiteralTypes1.ts, 178, 65)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->h2 : Symbol(h2, Decl(templateLiteralTypes1.ts, 178, 74)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->i2 : Symbol(i2, Decl(templateLiteralTypes1.ts, 178, 83)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->j2 : Symbol(j2, Decl(templateLiteralTypes1.ts, 178, 92)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>U2 : Symbol(U2, Decl(templateLiteralTypes1.ts, 181, 98)) +>a2 : Symbol(a2, Decl(templateLiteralTypes1.ts, 182, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>b2 : Symbol(b2, Decl(templateLiteralTypes1.ts, 182, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>c2 : Symbol(c2, Decl(templateLiteralTypes1.ts, 182, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>d2 : Symbol(d2, Decl(templateLiteralTypes1.ts, 182, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>e2 : Symbol(e2, Decl(templateLiteralTypes1.ts, 182, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>f2 : Symbol(f2, Decl(templateLiteralTypes1.ts, 182, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>g2 : Symbol(g2, Decl(templateLiteralTypes1.ts, 182, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>h2 : Symbol(h2, Decl(templateLiteralTypes1.ts, 182, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>i2 : Symbol(i2, Decl(templateLiteralTypes1.ts, 182, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>j2 : Symbol(j2, Decl(templateLiteralTypes1.ts, 182, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) type U3 = {a3:A} | {b3:A} | {c3:A} | {d3:A} | {e3:A} | {f3:A} | {g3:A} | {h3:A} | {i3:A} | {j3:A}; ->U3 : Symbol(U3, Decl(templateLiteralTypes1.ts, 178, 98)) ->a3 : Symbol(a3, Decl(templateLiteralTypes1.ts, 179, 11)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->b3 : Symbol(b3, Decl(templateLiteralTypes1.ts, 179, 20)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->c3 : Symbol(c3, Decl(templateLiteralTypes1.ts, 179, 29)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->d3 : Symbol(d3, Decl(templateLiteralTypes1.ts, 179, 38)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->e3 : Symbol(e3, Decl(templateLiteralTypes1.ts, 179, 47)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->f3 : Symbol(f3, Decl(templateLiteralTypes1.ts, 179, 56)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->g3 : Symbol(g3, Decl(templateLiteralTypes1.ts, 179, 65)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->h3 : Symbol(h3, Decl(templateLiteralTypes1.ts, 179, 74)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->i3 : Symbol(i3, Decl(templateLiteralTypes1.ts, 179, 83)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->j3 : Symbol(j3, Decl(templateLiteralTypes1.ts, 179, 92)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>U3 : Symbol(U3, Decl(templateLiteralTypes1.ts, 182, 98)) +>a3 : Symbol(a3, Decl(templateLiteralTypes1.ts, 183, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>b3 : Symbol(b3, Decl(templateLiteralTypes1.ts, 183, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>c3 : Symbol(c3, Decl(templateLiteralTypes1.ts, 183, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>d3 : Symbol(d3, Decl(templateLiteralTypes1.ts, 183, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>e3 : Symbol(e3, Decl(templateLiteralTypes1.ts, 183, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>f3 : Symbol(f3, Decl(templateLiteralTypes1.ts, 183, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>g3 : Symbol(g3, Decl(templateLiteralTypes1.ts, 183, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>h3 : Symbol(h3, Decl(templateLiteralTypes1.ts, 183, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>i3 : Symbol(i3, Decl(templateLiteralTypes1.ts, 183, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>j3 : Symbol(j3, Decl(templateLiteralTypes1.ts, 183, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) type U4 = {a4:A} | {b4:A} | {c4:A} | {d4:A} | {e4:A} | {f4:A} | {g4:A} | {h4:A} | {i4:A} | {j4:A}; ->U4 : Symbol(U4, Decl(templateLiteralTypes1.ts, 179, 98)) ->a4 : Symbol(a4, Decl(templateLiteralTypes1.ts, 180, 11)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->b4 : Symbol(b4, Decl(templateLiteralTypes1.ts, 180, 20)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->c4 : Symbol(c4, Decl(templateLiteralTypes1.ts, 180, 29)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->d4 : Symbol(d4, Decl(templateLiteralTypes1.ts, 180, 38)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->e4 : Symbol(e4, Decl(templateLiteralTypes1.ts, 180, 47)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->f4 : Symbol(f4, Decl(templateLiteralTypes1.ts, 180, 56)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->g4 : Symbol(g4, Decl(templateLiteralTypes1.ts, 180, 65)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->h4 : Symbol(h4, Decl(templateLiteralTypes1.ts, 180, 74)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->i4 : Symbol(i4, Decl(templateLiteralTypes1.ts, 180, 83)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->j4 : Symbol(j4, Decl(templateLiteralTypes1.ts, 180, 92)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>U4 : Symbol(U4, Decl(templateLiteralTypes1.ts, 183, 98)) +>a4 : Symbol(a4, Decl(templateLiteralTypes1.ts, 184, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>b4 : Symbol(b4, Decl(templateLiteralTypes1.ts, 184, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>c4 : Symbol(c4, Decl(templateLiteralTypes1.ts, 184, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>d4 : Symbol(d4, Decl(templateLiteralTypes1.ts, 184, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>e4 : Symbol(e4, Decl(templateLiteralTypes1.ts, 184, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>f4 : Symbol(f4, Decl(templateLiteralTypes1.ts, 184, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>g4 : Symbol(g4, Decl(templateLiteralTypes1.ts, 184, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>h4 : Symbol(h4, Decl(templateLiteralTypes1.ts, 184, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>i4 : Symbol(i4, Decl(templateLiteralTypes1.ts, 184, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>j4 : Symbol(j4, Decl(templateLiteralTypes1.ts, 184, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) type U5 = {a5:A} | {b5:A} | {c5:A} | {d5:A} | {e5:A} | {f5:A} | {g5:A} | {h5:A} | {i5:A} | {j5:A}; ->U5 : Symbol(U5, Decl(templateLiteralTypes1.ts, 180, 98)) ->a5 : Symbol(a5, Decl(templateLiteralTypes1.ts, 181, 11)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->b5 : Symbol(b5, Decl(templateLiteralTypes1.ts, 181, 20)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->c5 : Symbol(c5, Decl(templateLiteralTypes1.ts, 181, 29)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->d5 : Symbol(d5, Decl(templateLiteralTypes1.ts, 181, 38)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->e5 : Symbol(e5, Decl(templateLiteralTypes1.ts, 181, 47)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->f5 : Symbol(f5, Decl(templateLiteralTypes1.ts, 181, 56)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->g5 : Symbol(g5, Decl(templateLiteralTypes1.ts, 181, 65)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->h5 : Symbol(h5, Decl(templateLiteralTypes1.ts, 181, 74)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->i5 : Symbol(i5, Decl(templateLiteralTypes1.ts, 181, 83)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) ->j5 : Symbol(j5, Decl(templateLiteralTypes1.ts, 181, 92)) ->A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>U5 : Symbol(U5, Decl(templateLiteralTypes1.ts, 184, 98)) +>a5 : Symbol(a5, Decl(templateLiteralTypes1.ts, 185, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>b5 : Symbol(b5, Decl(templateLiteralTypes1.ts, 185, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>c5 : Symbol(c5, Decl(templateLiteralTypes1.ts, 185, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>d5 : Symbol(d5, Decl(templateLiteralTypes1.ts, 185, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>e5 : Symbol(e5, Decl(templateLiteralTypes1.ts, 185, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>f5 : Symbol(f5, Decl(templateLiteralTypes1.ts, 185, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>g5 : Symbol(g5, Decl(templateLiteralTypes1.ts, 185, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>h5 : Symbol(h5, Decl(templateLiteralTypes1.ts, 185, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>i5 : Symbol(i5, Decl(templateLiteralTypes1.ts, 185, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) +>j5 : Symbol(j5, Decl(templateLiteralTypes1.ts, 185, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 175, 48)) type U100000 = U1 & U2 & U3 & U4 & U5; // Error ->U100000 : Symbol(U100000, Decl(templateLiteralTypes1.ts, 181, 98)) ->U1 : Symbol(U1, Decl(templateLiteralTypes1.ts, 175, 13)) ->U2 : Symbol(U2, Decl(templateLiteralTypes1.ts, 177, 98)) ->U3 : Symbol(U3, Decl(templateLiteralTypes1.ts, 178, 98)) ->U4 : Symbol(U4, Decl(templateLiteralTypes1.ts, 179, 98)) ->U5 : Symbol(U5, Decl(templateLiteralTypes1.ts, 180, 98)) +>U100000 : Symbol(U100000, Decl(templateLiteralTypes1.ts, 185, 98)) +>U1 : Symbol(U1, Decl(templateLiteralTypes1.ts, 179, 13)) +>U2 : Symbol(U2, Decl(templateLiteralTypes1.ts, 181, 98)) +>U3 : Symbol(U3, Decl(templateLiteralTypes1.ts, 182, 98)) +>U4 : Symbol(U4, Decl(templateLiteralTypes1.ts, 183, 98)) +>U5 : Symbol(U5, Decl(templateLiteralTypes1.ts, 184, 98)) type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; ->Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 187, 38)) type D100000 = `${Digits}${Digits}${Digits}${Digits}${Digits}`; // Error ->D100000 : Symbol(D100000, Decl(templateLiteralTypes1.ts, 185, 52)) ->Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) ->Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) ->Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) ->Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) ->Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) +>D100000 : Symbol(D100000, Decl(templateLiteralTypes1.ts, 189, 52)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 187, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 187, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 187, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 187, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 187, 38)) type TDigits = [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9]; ->TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 191, 63)) type T100000 = [...TDigits, ...TDigits, ...TDigits, ...TDigits, ...TDigits]; // Error ->T100000 : Symbol(T100000, Decl(templateLiteralTypes1.ts, 189, 73)) ->TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) ->TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) ->TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) ->TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) ->TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) +>T100000 : Symbol(T100000, Decl(templateLiteralTypes1.ts, 193, 73)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 191, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 191, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 191, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 191, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 191, 63)) diff --git a/tests/baselines/reference/templateLiteralTypes1.types b/tests/baselines/reference/templateLiteralTypes1.types index 400b77b612d..d8b55f4971c 100644 --- a/tests/baselines/reference/templateLiteralTypes1.types +++ b/tests/baselines/reference/templateLiteralTypes1.types @@ -107,12 +107,12 @@ function fa2(x: { [P in B as `p_$ // String transformations using recursive conditional types -type Join = +type Join = >Join : Join T extends [] ? '' : - T extends [unknown] ? `${T[0]}` : - T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + T extends [string | number | boolean | bigint] ? `${T[0]}` : + T extends [string | number | boolean | bigint, ...infer U] ? `${T[0]}${D}${Join}` : string; type TJ1 = Join<[1, 2, 3, 4], '.'> @@ -395,6 +395,11 @@ type S1 = T extends `foo${infer U}bar` ? S2 : never; type S2 = S; >S2 : S +// Check that infer T declarations are validated + +type TV1 = `${infer X}`; +>TV1 : `${X}` + // Batched single character inferences for lower recursion depth type Chars = diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes1.ts b/tests/cases/conformance/types/literal/templateLiteralTypes1.ts index 55952d44bd6..1cd0b065343 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes1.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes1.ts @@ -44,10 +44,10 @@ function fa2(x: { [P in B as `p_$ // String transformations using recursive conditional types -type Join = +type Join = T extends [] ? '' : - T extends [unknown] ? `${T[0]}` : - T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + T extends [string | number | boolean | bigint] ? `${T[0]}` : + T extends [string | number | boolean | bigint, ...infer U] ? `${T[0]}${D}${Join}` : string; type TJ1 = Join<[1, 2, 3, 4], '.'> @@ -163,6 +163,10 @@ getPropValue(obj, s); // unknown type S1 = T extends `foo${infer U}bar` ? S2 : never; type S2 = S; +// Check that infer T declarations are validated + +type TV1 = `${infer X}`; + // Batched single character inferences for lower recursion depth type Chars =