From 0758d841a56b8410330c7664465f01fcee001223 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 2 Mar 2022 14:25:20 -0800 Subject: [PATCH 01/10] More specific inference for constrained 'infer' types in template literal types --- src/compiler/checker.ts | 87 +++- .../templateLiteralTypes4.errors.txt | 107 +++++ .../reference/templateLiteralTypes4.js | 182 ++++++++ .../reference/templateLiteralTypes4.symbols | 402 ++++++++++++++++++ .../reference/templateLiteralTypes4.types | 244 +++++++++++ .../types/literal/templateLiteralTypes4.ts | 100 +++++ 6 files changed, 1116 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/templateLiteralTypes4.errors.txt create mode 100644 tests/baselines/reference/templateLiteralTypes4.js create mode 100644 tests/baselines/reference/templateLiteralTypes4.symbols create mode 100644 tests/baselines/reference/templateLiteralTypes4.types create mode 100644 tests/cases/conformance/types/literal/templateLiteralTypes4.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f49cfb3618928..c3d91069d6670 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22109,13 +22109,31 @@ namespace ts { sourceEnd.slice(sourceEnd.length - endLen) !== targetEnd.slice(targetEnd.length - endLen); } - function isValidBigIntString(s: string): boolean { + /** + * Tests whether the provided string can be parsed as a number. + * @param s The string to test. + * @param roundTripOnly Indicates the resulting number matches the input when converted back to a string. + */ + function isValidNumberString(s: string, roundTripOnly: boolean): boolean { + if (s === "") return false; + const n = +s; + return isFinite(n) && (!roundTripOnly || "" + n === s); + } + + /** + * Tests whether the provided string can be parsed as a bigint. + * @param s The string to test. + * @param roundTripOnly Indicates the resulting bigint matches the input when converted back to a string. + */ + function isValidBigIntString(s: string, roundTripOnly: boolean): boolean { + if (s === "") return false; const scanner = createScanner(ScriptTarget.ESNext, /*skipTrivia*/ false); let success = true; scanner.setOnError(() => success = false); scanner.setText(s + "n"); let result = scanner.scan(); - if (result === SyntaxKind.MinusToken) { + const negative = result === SyntaxKind.MinusToken; + if (negative) { result = scanner.scan(); } const flags = scanner.getTokenFlags(); @@ -22124,7 +22142,8 @@ namespace ts { // * a bigint can be scanned, and that when it is scanned, it is // * the full length of the input string (so the scanner is one character beyond the augmented input length) // * it does not contain a numeric seperator (the `BigInt` constructor does not accept a numeric seperator in its input) - return success && result === SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator); + return success && result === SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator) + && (!roundTripOnly || s === pseudoBigIntToString({ negative, base10Value: parsePseudoBigInt(scanner.getTokenValue()) })); } function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean { @@ -22133,8 +22152,8 @@ namespace ts { } if (source.flags & TypeFlags.StringLiteral) { const value = (source as StringLiteralType).value; - return !!(target.flags & TypeFlags.Number && value !== "" && isFinite(+value) || - target.flags & TypeFlags.BigInt && value !== "" && isValidBigIntString(value) || + return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) || + target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) || target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName); } if (source.flags & TypeFlags.TemplateLiteral) { @@ -22712,7 +22731,63 @@ namespace ts { // succeed. That would be a pointless and confusing outcome. if (matches || every(target.texts, s => s.length === 0)) { for (let i = 0; i < types.length; i++) { - inferFromTypes(matches ? matches[i] : neverType, types[i]); + const source = matches ? matches[i] : neverType; + const target = types[i]; + + // If we are inferring from a string literal type to a type variable whose constraint includes one of the + // allowed template literal placeholder types, infer from a literal type corresponding to the constraint. + let sourceTypes: Type[] | undefined; + if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.TypeVariable) { + const inferenceContext = getInferenceInfoForType(target); + const constraint = inferenceContext ? getConstraintOfTypeParameter(inferenceContext.typeParameter) : undefined; + if (inferenceContext && constraint) { + const str = (source as StringLiteralType).value; + const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint]; + for (const constraintType of constraintTypes) { + if (constraintType.flags & TypeFlags.StringLike) { + sourceTypes ??= []; + sourceTypes.push(source); + } + if (constraintType.flags & TypeFlags.NumberLike && isValidNumberString(str, /*roundTripOnly*/ true)) { + sourceTypes ??= []; + sourceTypes.push(getNumberLiteralType(+str)); + } + if (constraintType.flags & TypeFlags.BigIntLike && isValidBigIntString(str, /*roundTripOnly*/ true)) { + const negative = str.startsWith("-"); + const base10Value = parsePseudoBigInt(`${negative ? str.slice(1) : str}n`); + sourceTypes ??= []; + sourceTypes.push(getBigIntLiteralType({ negative, base10Value })); + } + if (constraintType.flags & TypeFlags.BooleanLike) { + if (str === trueType.intrinsicName) { + sourceTypes ??= []; + sourceTypes.push(trueType); + } + else if (str === falseType.intrinsicName) { + sourceTypes ??= []; + sourceTypes.push(falseType); + } + } + if (constraintType.flags & TypeFlags.Null && str === nullType.intrinsicName) { + sourceTypes ??= []; + sourceTypes.push(nullType); + } + if (constraintType.flags & TypeFlags.Undefined && str === undefinedType.intrinsicName) { + sourceTypes ??= []; + sourceTypes.push(undefinedType); + } + } + } + } + + if (sourceTypes) { + for (const source of sourceTypes) { + inferFromTypes(source, target); + } + } + else { + inferFromTypes(source, target); + } } } } diff --git a/tests/baselines/reference/templateLiteralTypes4.errors.txt b/tests/baselines/reference/templateLiteralTypes4.errors.txt new file mode 100644 index 0000000000000..e92d5cafb6d3c --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes4.errors.txt @@ -0,0 +1,107 @@ +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(93,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(97,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. + + +==== tests/cases/conformance/types/literal/templateLiteralTypes4.ts (2 errors) ==== + type Is = T; + + type T0 = "100" extends `${Is}` ? N : never; // 100 + type T1 = "-100" extends `${Is}` ? N : never; // -100 + type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 + type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) + type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) + type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) + type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) + type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) + type T8 = "abcd" extends `${Is}` ? N : never; // never + + type T10 = "100" extends `${Is}` ? N : never; // 100n + type T11 = "-100" extends `${Is}` ? N : never; // -100n + type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) + type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) + type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) + type T15 = "1.1" extends `${Is}` ? N : never; // never + type T16 = "10e2" extends `${Is}` ? N : never; // never + type T17 = "abcd" extends `${Is}` ? N : never; // never + + type T20 = "true" extends `${Is}` ? T : never; // true + type T21 = "false" extends `${Is}` ? T : never; // false + type T22 = "abcd" extends `${Is}` ? T : never; // never + + type T30 = "null" extends `${Is}` ? T : never; // null + type T31 = "abcd" extends `${Is}` ? T : never; // never + + type T40 = "undefined" extends `${Is}` ? T : never; // undefined + type T41 = "abcd" extends `${Is}` ? T : never; // never + + type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n + type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 + type T52 = "true" extends `${Is}` ? T : never; // "true" | true + type T53 = "false" extends `${Is}` ? T : never; // "false" | false + type T54 = "null" extends `${Is}` ? T : never; // "null" | null + type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined + + type NumberFor = S extends `${Is}` ? N : never; + type T60 = NumberFor<"100">; // 100 + type T61 = NumberFor; // never + type T62 = NumberFor; // never + + // example use case: + interface FieldDefinition { + readonly name: string; + readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; + } + + type FieldType = + T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : + T extends "f32" | "f64" ? bigint : + never; + + // Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` + type TypedObjectNamedMembers = { + [P in TDef[number]["name"]]: FieldType["type"]>; + }; + + // Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` + type TypedObjectOrdinalMembers = { + [I in Extract]: FieldType["type"]>; + }; + + // Default members + interface TypedObjectMembers { + // get/set a field by name + get(key: K): FieldType["type"]>; + set(key: K, value: FieldType["type"]>): void; + + // get/set a field by index + getIndex>(index: I): FieldType["type"]>; + setIndex>(index: I, value: FieldType["type"]>): void; + } + + // Use constrained `infer` in template literal to get ordinal indices as numbers: + type IndicesOf = NumberFor>; // ordinal indices as number literals + + type TypedObject = + & TypedObjectMembers + & TypedObjectNamedMembers + & TypedObjectOrdinalMembers; + + // NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type + type Point = TypedObject<[ + { name: "x", type: "f64" }, + { name: "y", type: "f64" }, + ]>; + + declare const p: Point; + p.getIndex(0); // ok, 0 is a valid index + p.getIndex(1); // ok, 1 is a valid index + p.getIndex(2); // error, 2 is not a valid index + ~ +!!! error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. + + p.setIndex(0, 0); // ok, 0 is a valid index + p.setIndex(1, 0); // ok, 1 is a valid index + p.setIndex(2, 3); // error, 2 is not a valid index + ~ +!!! error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. + \ No newline at end of file diff --git a/tests/baselines/reference/templateLiteralTypes4.js b/tests/baselines/reference/templateLiteralTypes4.js new file mode 100644 index 0000000000000..c3654864b1d70 --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes4.js @@ -0,0 +1,182 @@ +//// [templateLiteralTypes4.ts] +type Is = T; + +type T0 = "100" extends `${Is}` ? N : never; // 100 +type T1 = "-100" extends `${Is}` ? N : never; // -100 +type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 +type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) +type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) +type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) +type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) +type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) +type T8 = "abcd" extends `${Is}` ? N : never; // never + +type T10 = "100" extends `${Is}` ? N : never; // 100n +type T11 = "-100" extends `${Is}` ? N : never; // -100n +type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T15 = "1.1" extends `${Is}` ? N : never; // never +type T16 = "10e2" extends `${Is}` ? N : never; // never +type T17 = "abcd" extends `${Is}` ? N : never; // never + +type T20 = "true" extends `${Is}` ? T : never; // true +type T21 = "false" extends `${Is}` ? T : never; // false +type T22 = "abcd" extends `${Is}` ? T : never; // never + +type T30 = "null" extends `${Is}` ? T : never; // null +type T31 = "abcd" extends `${Is}` ? T : never; // never + +type T40 = "undefined" extends `${Is}` ? T : never; // undefined +type T41 = "abcd" extends `${Is}` ? T : never; // never + +type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n +type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 +type T52 = "true" extends `${Is}` ? T : never; // "true" | true +type T53 = "false" extends `${Is}` ? T : never; // "false" | false +type T54 = "null" extends `${Is}` ? T : never; // "null" | null +type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined + +type NumberFor = S extends `${Is}` ? N : never; +type T60 = NumberFor<"100">; // 100 +type T61 = NumberFor; // never +type T62 = NumberFor; // never + +// example use case: +interface FieldDefinition { + readonly name: string; + readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; +} + +type FieldType = + T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : + T extends "f32" | "f64" ? bigint : + never; + +// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectNamedMembers = { + [P in TDef[number]["name"]]: FieldType["type"]>; +}; + +// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectOrdinalMembers = { + [I in Extract]: FieldType["type"]>; +}; + +// Default members +interface TypedObjectMembers { + // get/set a field by name + get(key: K): FieldType["type"]>; + set(key: K, value: FieldType["type"]>): void; + + // get/set a field by index + getIndex>(index: I): FieldType["type"]>; + setIndex>(index: I, value: FieldType["type"]>): void; +} + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndicesOf = NumberFor>; // ordinal indices as number literals + +type TypedObject = + & TypedObjectMembers + & TypedObjectNamedMembers + & TypedObjectOrdinalMembers; + +// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type +type Point = TypedObject<[ + { name: "x", type: "f64" }, + { name: "y", type: "f64" }, +]>; + +declare const p: Point; +p.getIndex(0); // ok, 0 is a valid index +p.getIndex(1); // ok, 1 is a valid index +p.getIndex(2); // error, 2 is not a valid index + +p.setIndex(0, 0); // ok, 0 is a valid index +p.setIndex(1, 0); // ok, 1 is a valid index +p.setIndex(2, 3); // error, 2 is not a valid index + + +//// [templateLiteralTypes4.js] +"use strict"; +p.getIndex(0); // ok, 0 is a valid index +p.getIndex(1); // ok, 1 is a valid index +p.getIndex(2); // error, 2 is not a valid index +p.setIndex(0, 0); // ok, 0 is a valid index +p.setIndex(1, 0); // ok, 1 is a valid index +p.setIndex(2, 3); // error, 2 is not a valid index + + +//// [templateLiteralTypes4.d.ts] +declare type Is = T; +declare type T0 = "100" extends `${Is}` ? N : never; +declare type T1 = "-100" extends `${Is}` ? N : never; +declare type T2 = "1.1" extends `${Is}` ? N : never; +declare type T3 = "8e-11" extends `${Is}` ? N : never; +declare type T4 = "0x10" extends `${Is}` ? N : never; +declare type T5 = "0o10" extends `${Is}` ? N : never; +declare type T6 = "0b10" extends `${Is}` ? N : never; +declare type T7 = "10e2" extends `${Is}` ? N : never; +declare type T8 = "abcd" extends `${Is}` ? N : never; +declare type T10 = "100" extends `${Is}` ? N : never; +declare type T11 = "-100" extends `${Is}` ? N : never; +declare type T12 = "0x10" extends `${Is}` ? N : never; +declare type T13 = "0o10" extends `${Is}` ? N : never; +declare type T14 = "0b10" extends `${Is}` ? N : never; +declare type T15 = "1.1" extends `${Is}` ? N : never; +declare type T16 = "10e2" extends `${Is}` ? N : never; +declare type T17 = "abcd" extends `${Is}` ? N : never; +declare type T20 = "true" extends `${Is}` ? T : never; +declare type T21 = "false" extends `${Is}` ? T : never; +declare type T22 = "abcd" extends `${Is}` ? T : never; +declare type T30 = "null" extends `${Is}` ? T : never; +declare type T31 = "abcd" extends `${Is}` ? T : never; +declare type T40 = "undefined" extends `${Is}` ? T : never; +declare type T41 = "abcd" extends `${Is}` ? T : never; +declare type T50 = "100" extends `${Is}` ? T : never; +declare type T51 = "1.1" extends `${Is}` ? T : never; +declare type T52 = "true" extends `${Is}` ? T : never; +declare type T53 = "false" extends `${Is}` ? T : never; +declare type T54 = "null" extends `${Is}` ? T : never; +declare type T55 = "undefined" extends `${Is}` ? T : never; +declare type NumberFor = S extends `${Is}` ? N : never; +declare type T60 = NumberFor<"100">; +declare type T61 = NumberFor; +declare type T62 = NumberFor; +interface FieldDefinition { + readonly name: string; + readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; +} +declare type FieldType = T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : T extends "f32" | "f64" ? bigint : never; +declare type TypedObjectNamedMembers = { + [P in TDef[number]["name"]]: FieldType["type"]>; +}; +declare type TypedObjectOrdinalMembers = { + [I in Extract]: FieldType["type"]>; +}; +interface TypedObjectMembers { + get(key: K): FieldType["type"]>; + set(key: K, value: FieldType["type"]>): void; + getIndex>(index: I): FieldType["type"]>; + setIndex>(index: I, value: FieldType["type"]>): void; +} +declare type IndicesOf = NumberFor>; +declare type TypedObject = TypedObjectMembers & TypedObjectNamedMembers & TypedObjectOrdinalMembers; +declare type Point = TypedObject<[ + { + name: "x"; + type: "f64"; + }, + { + name: "y"; + type: "f64"; + } +]>; +declare const p: Point; diff --git a/tests/baselines/reference/templateLiteralTypes4.symbols b/tests/baselines/reference/templateLiteralTypes4.symbols new file mode 100644 index 0000000000000..58a08396f3828 --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes4.symbols @@ -0,0 +1,402 @@ +=== tests/cases/conformance/types/literal/templateLiteralTypes4.ts === +type Is = T; +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 0, 8)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 0, 20)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 0, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 0, 8)) + +type T0 = "100" extends `${Is}` ? N : never; // 100 +>T0 : Symbol(T0, Decl(templateLiteralTypes4.ts, 0, 28)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 35)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 35)) + +type T1 = "-100" extends `${Is}` ? N : never; // -100 +>T1 : Symbol(T1, Decl(templateLiteralTypes4.ts, 2, 61)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 36)) + +type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 +>T2 : Symbol(T2, Decl(templateLiteralTypes4.ts, 3, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 35)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 35)) + +type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) +>T3 : Symbol(T3, Decl(templateLiteralTypes4.ts, 4, 61)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 37)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 37)) + +type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) +>T4 : Symbol(T4, Decl(templateLiteralTypes4.ts, 5, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 36)) + +type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) +>T5 : Symbol(T5, Decl(templateLiteralTypes4.ts, 6, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 36)) + +type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) +>T6 : Symbol(T6, Decl(templateLiteralTypes4.ts, 7, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 36)) + +type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) +>T7 : Symbol(T7, Decl(templateLiteralTypes4.ts, 8, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 36)) + +type T8 = "abcd" extends `${Is}` ? N : never; // never +>T8 : Symbol(T8, Decl(templateLiteralTypes4.ts, 9, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 36)) + +type T10 = "100" extends `${Is}` ? N : never; // 100n +>T10 : Symbol(T10, Decl(templateLiteralTypes4.ts, 10, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 36)) + +type T11 = "-100" extends `${Is}` ? N : never; // -100n +>T11 : Symbol(T11, Decl(templateLiteralTypes4.ts, 12, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 37)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 37)) + +type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) +>T12 : Symbol(T12, Decl(templateLiteralTypes4.ts, 13, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 37)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 37)) + +type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) +>T13 : Symbol(T13, Decl(templateLiteralTypes4.ts, 14, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 37)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 37)) + +type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) +>T14 : Symbol(T14, Decl(templateLiteralTypes4.ts, 15, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 37)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 37)) + +type T15 = "1.1" extends `${Is}` ? N : never; // never +>T15 : Symbol(T15, Decl(templateLiteralTypes4.ts, 16, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 36)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 36)) + +type T16 = "10e2" extends `${Is}` ? N : never; // never +>T16 : Symbol(T16, Decl(templateLiteralTypes4.ts, 17, 62)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 37)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 37)) + +type T17 = "abcd" extends `${Is}` ? N : never; // never +>T17 : Symbol(T17, Decl(templateLiteralTypes4.ts, 18, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 37)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 37)) + +type T20 = "true" extends `${Is}` ? T : never; // true +>T20 : Symbol(T20, Decl(templateLiteralTypes4.ts, 19, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 37)) + +type T21 = "false" extends `${Is}` ? T : never; // false +>T21 : Symbol(T21, Decl(templateLiteralTypes4.ts, 21, 64)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 38)) + +type T22 = "abcd" extends `${Is}` ? T : never; // never +>T22 : Symbol(T22, Decl(templateLiteralTypes4.ts, 22, 65)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 37)) + +type T30 = "null" extends `${Is}` ? T : never; // null +>T30 : Symbol(T30, Decl(templateLiteralTypes4.ts, 23, 64)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 25, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 25, 37)) + +type T31 = "abcd" extends `${Is}` ? T : never; // never +>T31 : Symbol(T31, Decl(templateLiteralTypes4.ts, 25, 61)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 37)) + +type T40 = "undefined" extends `${Is}` ? T : never; // undefined +>T40 : Symbol(T40, Decl(templateLiteralTypes4.ts, 26, 61)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 42)) + +type T41 = "abcd" extends `${Is}` ? T : never; // never +>T41 : Symbol(T41, Decl(templateLiteralTypes4.ts, 28, 71)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 37)) + +type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n +>T50 : Symbol(T50, Decl(templateLiteralTypes4.ts, 29, 66)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 36)) + +type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 +>T51 : Symbol(T51, Decl(templateLiteralTypes4.ts, 31, 109)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 36)) + +type T52 = "true" extends `${Is}` ? T : never; // "true" | true +>T52 : Symbol(T52, Decl(templateLiteralTypes4.ts, 32, 109)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 37)) + +type T53 = "false" extends `${Is}` ? T : never; // "false" | false +>T53 : Symbol(T53, Decl(templateLiteralTypes4.ts, 33, 110)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 38)) + +type T54 = "null" extends `${Is}` ? T : never; // "null" | null +>T54 : Symbol(T54, Decl(templateLiteralTypes4.ts, 34, 111)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 37)) + +type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined +>T55 : Symbol(T55, Decl(templateLiteralTypes4.ts, 35, 110)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 42)) + +type NumberFor = S extends `${Is}` ? N : never; +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 38, 15)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 38, 15)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 38, 56)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 38, 56)) + +type T60 = NumberFor<"100">; // 100 +>T60 : Symbol(T60, Decl(templateLiteralTypes4.ts, 38, 82)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) + +type T61 = NumberFor; // never +>T61 : Symbol(T61, Decl(templateLiteralTypes4.ts, 39, 28)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) + +type T62 = NumberFor; // never +>T62 : Symbol(T62, Decl(templateLiteralTypes4.ts, 40, 26)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) + +// example use case: +interface FieldDefinition { +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + + readonly name: string; +>name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 44, 27)) + + readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; +>type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 45, 26)) +} + +type FieldType = +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 15)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + + T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 15)) + + T extends "f32" | "f64" ? bigint : +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 15)) + + never; + +// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectNamedMembers = { +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 52, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 55, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + + [P in TDef[number]["name"]]: FieldType["type"]>; +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 56, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 55, 29)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 55, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 56, 66)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 56, 5)) + +}; + +// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectOrdinalMembers = { +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 57, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 60, 31)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + + [I in Extract]: FieldType["type"]>; +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 61, 5)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 60, 31)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 60, 31)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 61, 5)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + +}; + +// Default members +interface TypedObjectMembers { +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 62, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + + // get/set a field by name + get(key: K): FieldType["type"]>; +>get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 65, 71)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 67, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 67, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 67, 8)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 67, 82)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 67, 8)) + + set(key: K, value: FieldType["type"]>): void; +>set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 67, 112)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 68, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 68, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 68, 8)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 68, 47)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 68, 88)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 68, 8)) + + // get/set a field by index + getIndex>(index: I): FieldType["type"]>; +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 71, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 73, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 71, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 71, 13)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 71, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + + setIndex>(index: I, value: FieldType["type"]>): void; +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 72, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 73, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 72, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 72, 13)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 72, 49)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 72, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +} + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndicesOf = NumberFor>; // ordinal indices as number literals +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 73, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) + +type TypedObject = +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 76, 56)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) + + & TypedObjectMembers +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 62, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) + + & TypedObjectNamedMembers +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 52, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) + + & TypedObjectOrdinalMembers; +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 57, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) + +// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type +type Point = TypedObject<[ +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 81, 38)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 76, 56)) + + { name: "x", type: "f64" }, +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 85, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 85, 16)) + + { name: "y", type: "f64" }, +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 86, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 86, 16)) + +]>; + +declare const p: Point; +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 81, 38)) + +p.getIndex(0); // ok, 0 is a valid index +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) + +p.getIndex(1); // ok, 1 is a valid index +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) + +p.getIndex(2); // error, 2 is not a valid index +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) + +p.setIndex(0, 0); // ok, 0 is a valid index +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) + +p.setIndex(1, 0); // ok, 1 is a valid index +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) + +p.setIndex(2, 3); // error, 2 is not a valid index +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) + diff --git a/tests/baselines/reference/templateLiteralTypes4.types b/tests/baselines/reference/templateLiteralTypes4.types new file mode 100644 index 0000000000000..e458ab1b4413f --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes4.types @@ -0,0 +1,244 @@ +=== tests/cases/conformance/types/literal/templateLiteralTypes4.ts === +type Is = T; +>Is : T + +type T0 = "100" extends `${Is}` ? N : never; // 100 +>T0 : 100 + +type T1 = "-100" extends `${Is}` ? N : never; // -100 +>T1 : -100 + +type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 +>T2 : 1.1 + +type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) +>T3 : 8e-11 + +type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) +>T4 : number + +type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) +>T5 : number + +type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) +>T6 : number + +type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) +>T7 : number + +type T8 = "abcd" extends `${Is}` ? N : never; // never +>T8 : never + +type T10 = "100" extends `${Is}` ? N : never; // 100n +>T10 : 100n + +type T11 = "-100" extends `${Is}` ? N : never; // -100n +>T11 : -100n + +type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) +>T12 : bigint + +type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) +>T13 : bigint + +type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) +>T14 : bigint + +type T15 = "1.1" extends `${Is}` ? N : never; // never +>T15 : never + +type T16 = "10e2" extends `${Is}` ? N : never; // never +>T16 : never + +type T17 = "abcd" extends `${Is}` ? N : never; // never +>T17 : never + +type T20 = "true" extends `${Is}` ? T : never; // true +>T20 : true + +type T21 = "false" extends `${Is}` ? T : never; // false +>T21 : false + +type T22 = "abcd" extends `${Is}` ? T : never; // never +>T22 : never + +type T30 = "null" extends `${Is}` ? T : never; // null +>T30 : null +>null : null + +type T31 = "abcd" extends `${Is}` ? T : never; // never +>T31 : never +>null : null + +type T40 = "undefined" extends `${Is}` ? T : never; // undefined +>T40 : undefined + +type T41 = "abcd" extends `${Is}` ? T : never; // never +>T41 : never + +type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n +>T50 : "100" | 100 | 100n +>null : null + +type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 +>T51 : "1.1" | 1.1 +>null : null + +type T52 = "true" extends `${Is}` ? T : never; // "true" | true +>T52 : true | "true" +>null : null + +type T53 = "false" extends `${Is}` ? T : never; // "false" | false +>T53 : false | "false" +>null : null + +type T54 = "null" extends `${Is}` ? T : never; // "null" | null +>T54 : "null" | null +>null : null + +type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined +>T55 : "undefined" | undefined +>null : null + +type NumberFor = S extends `${Is}` ? N : never; +>NumberFor : NumberFor + +type T60 = NumberFor<"100">; // 100 +>T60 : 100 + +type T61 = NumberFor; // never +>T61 : never + +type T62 = NumberFor; // never +>T62 : never + +// example use case: +interface FieldDefinition { + readonly name: string; +>name : string + + readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; +>type : "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64" +} + +type FieldType = +>FieldType : FieldType + + T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : + T extends "f32" | "f64" ? bigint : + never; + +// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectNamedMembers = { +>TypedObjectNamedMembers : TypedObjectNamedMembers + + [P in TDef[number]["name"]]: FieldType["type"]>; +>name : P + +}; + +// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectOrdinalMembers = { +>TypedObjectOrdinalMembers : TypedObjectOrdinalMembers + + [I in Extract]: FieldType["type"]>; +}; + +// Default members +interface TypedObjectMembers { + // get/set a field by name + get(key: K): FieldType["type"]>; +>get : (key: K) => FieldType["type"]> +>key : K +>name : K + + set(key: K, value: FieldType["type"]>): void; +>set : (key: K, value: FieldType["type"]>) => void +>key : K +>value : FieldType["type"]> +>name : K + + // get/set a field by index + getIndex>(index: I): FieldType["type"]>; +>getIndex : >>(index: I) => FieldType["type"]> +>index : I + + setIndex>(index: I, value: FieldType["type"]>): void; +>setIndex : >>(index: I, value: FieldType["type"]>) => void +>index : I +>value : FieldType["type"]> +} + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndicesOf = NumberFor>; // ordinal indices as number literals +>IndicesOf : IndicesOf + +type TypedObject = +>TypedObject : TypedObject + + & TypedObjectMembers + & TypedObjectNamedMembers + & TypedObjectOrdinalMembers; + +// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type +type Point = TypedObject<[ +>Point : Point + + { name: "x", type: "f64" }, +>name : "x" +>type : "f64" + + { name: "y", type: "f64" }, +>name : "y" +>type : "f64" + +]>; + +declare const p: Point; +>p : Point + +p.getIndex(0); // ok, 0 is a valid index +>p.getIndex(0) : number +>p.getIndex : (index: I) => FieldType["type"]> +>p : Point +>getIndex : (index: I) => FieldType["type"]> +>0 : 0 + +p.getIndex(1); // ok, 1 is a valid index +>p.getIndex(1) : number +>p.getIndex : (index: I) => FieldType["type"]> +>p : Point +>getIndex : (index: I) => FieldType["type"]> +>1 : 1 + +p.getIndex(2); // error, 2 is not a valid index +>p.getIndex(2) : number +>p.getIndex : (index: I) => FieldType["type"]> +>p : Point +>getIndex : (index: I) => FieldType["type"]> +>2 : 2 + +p.setIndex(0, 0); // ok, 0 is a valid index +>p.setIndex(0, 0) : void +>p.setIndex : (index: I, value: FieldType["type"]>) => void +>p : Point +>setIndex : (index: I, value: FieldType["type"]>) => void +>0 : 0 +>0 : 0 + +p.setIndex(1, 0); // ok, 1 is a valid index +>p.setIndex(1, 0) : void +>p.setIndex : (index: I, value: FieldType["type"]>) => void +>p : Point +>setIndex : (index: I, value: FieldType["type"]>) => void +>1 : 1 +>0 : 0 + +p.setIndex(2, 3); // error, 2 is not a valid index +>p.setIndex(2, 3) : void +>p.setIndex : (index: I, value: FieldType["type"]>) => void +>p : Point +>setIndex : (index: I, value: FieldType["type"]>) => void +>2 : 2 +>3 : 3 + diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts new file mode 100644 index 0000000000000..5589725826088 --- /dev/null +++ b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts @@ -0,0 +1,100 @@ +// @strict: true +// @declaration: true + +type Is = T; + +type T0 = "100" extends `${Is}` ? N : never; // 100 +type T1 = "-100" extends `${Is}` ? N : never; // -100 +type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 +type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) +type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) +type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) +type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) +type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) +type T8 = "abcd" extends `${Is}` ? N : never; // never + +type T10 = "100" extends `${Is}` ? N : never; // 100n +type T11 = "-100" extends `${Is}` ? N : never; // -100n +type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T15 = "1.1" extends `${Is}` ? N : never; // never +type T16 = "10e2" extends `${Is}` ? N : never; // never +type T17 = "abcd" extends `${Is}` ? N : never; // never + +type T20 = "true" extends `${Is}` ? T : never; // true +type T21 = "false" extends `${Is}` ? T : never; // false +type T22 = "abcd" extends `${Is}` ? T : never; // never + +type T30 = "null" extends `${Is}` ? T : never; // null +type T31 = "abcd" extends `${Is}` ? T : never; // never + +type T40 = "undefined" extends `${Is}` ? T : never; // undefined +type T41 = "abcd" extends `${Is}` ? T : never; // never + +type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n +type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 +type T52 = "true" extends `${Is}` ? T : never; // "true" | true +type T53 = "false" extends `${Is}` ? T : never; // "false" | false +type T54 = "null" extends `${Is}` ? T : never; // "null" | null +type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined + +type NumberFor = S extends `${Is}` ? N : never; +type T60 = NumberFor<"100">; // 100 +type T61 = NumberFor; // never +type T62 = NumberFor; // never + +// example use case: +interface FieldDefinition { + readonly name: string; + readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; +} + +type FieldType = + T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : + T extends "f32" | "f64" ? bigint : + never; + +// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectNamedMembers = { + [P in TDef[number]["name"]]: FieldType["type"]>; +}; + +// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` +type TypedObjectOrdinalMembers = { + [I in Extract]: FieldType["type"]>; +}; + +// Default members +interface TypedObjectMembers { + // get/set a field by name + get(key: K): FieldType["type"]>; + set(key: K, value: FieldType["type"]>): void; + + // get/set a field by index + getIndex>(index: I): FieldType["type"]>; + setIndex>(index: I, value: FieldType["type"]>): void; +} + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndicesOf = NumberFor>; // ordinal indices as number literals + +type TypedObject = + & TypedObjectMembers + & TypedObjectNamedMembers + & TypedObjectOrdinalMembers; + +// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type +type Point = TypedObject<[ + { name: "x", type: "f64" }, + { name: "y", type: "f64" }, +]>; + +declare const p: Point; +p.getIndex(0); // ok, 0 is a valid index +p.getIndex(1); // ok, 1 is a valid index +p.getIndex(2); // error, 2 is not a valid index + +p.setIndex(0, 0); // ok, 0 is a valid index +p.setIndex(1, 0); // ok, 1 is a valid index +p.setIndex(2, 3); // error, 2 is not a valid index From c8da16ab9286ea83f161c8634a943478d636a542 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 22 Mar 2022 13:11:18 -0700 Subject: [PATCH 02/10] PR feedback --- src/compiler/checker.ts | 52 +++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c3d91069d6670..b9ca23f74b51b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22120,6 +22120,15 @@ namespace ts { return isFinite(n) && (!roundTripOnly || "" + n === s); } + /** + * @param text a valid bigint string excluding a trailing `n`, but including a possible prefix `-`. Use `isValidBigIntString(text, roundTripOnly)` before calling this function. + */ + function parseBigIntLiteralType(text: string) { + const negative = text.startsWith("-"); + const base10Value = parsePseudoBigInt(`${negative ? text.slice(1) : text}n`); + return getBigIntLiteralType({ negative, base10Value }); + } + /** * Tests whether the provided string can be parsed as a bigint. * @param s The string to test. @@ -22740,41 +22749,22 @@ namespace ts { if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.TypeVariable) { const inferenceContext = getInferenceInfoForType(target); const constraint = inferenceContext ? getConstraintOfTypeParameter(inferenceContext.typeParameter) : undefined; - if (inferenceContext && constraint) { + if (constraint) { const str = (source as StringLiteralType).value; const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint]; for (const constraintType of constraintTypes) { - if (constraintType.flags & TypeFlags.StringLike) { - sourceTypes ??= []; - sourceTypes.push(source); - } - if (constraintType.flags & TypeFlags.NumberLike && isValidNumberString(str, /*roundTripOnly*/ true)) { - sourceTypes ??= []; - sourceTypes.push(getNumberLiteralType(+str)); - } - if (constraintType.flags & TypeFlags.BigIntLike && isValidBigIntString(str, /*roundTripOnly*/ true)) { - const negative = str.startsWith("-"); - const base10Value = parsePseudoBigInt(`${negative ? str.slice(1) : str}n`); - sourceTypes ??= []; - sourceTypes.push(getBigIntLiteralType({ negative, base10Value })); - } - if (constraintType.flags & TypeFlags.BooleanLike) { - if (str === trueType.intrinsicName) { - sourceTypes ??= []; - sourceTypes.push(trueType); - } - else if (str === falseType.intrinsicName) { - sourceTypes ??= []; - sourceTypes.push(falseType); - } - } - if (constraintType.flags & TypeFlags.Null && str === nullType.intrinsicName) { - sourceTypes ??= []; - sourceTypes.push(nullType); - } - if (constraintType.flags & TypeFlags.Undefined && str === undefinedType.intrinsicName) { + const sourceType = + constraintType.flags & TypeFlags.StringLike ? source : + constraintType.flags & TypeFlags.NumberLike && isValidNumberString(str, /*roundTripOnly*/ true) ? getNumberLiteralType(+str) : + constraintType.flags & TypeFlags.BigIntLike && isValidBigIntString(str, /*roundTripOnly*/ true) ? parseBigIntLiteralType(str) : + constraintType.flags & TypeFlags.BooleanLike && str === trueType.intrinsicName ? trueType : + constraintType.flags & TypeFlags.BooleanLike && str === falseType.intrinsicName ? falseType : + constraintType.flags & TypeFlags.Null && str === nullType.intrinsicName ? nullType : + constraintType.flags & TypeFlags.Undefined && str === undefinedType.intrinsicName ? undefinedType : + undefined; + if (sourceType) { sourceTypes ??= []; - sourceTypes.push(undefinedType); + sourceTypes.push(sourceType); } } } From 55d4c3d3d0b996221cc91e5ec93d2e82e8bf8ad1 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 22 Mar 2022 14:40:52 -0700 Subject: [PATCH 03/10] Add inference priority for template type placeholders --- src/compiler/checker.ts | 3 ++ src/compiler/types.ts | 27 +++++++-------- .../reference/api/tsserverlibrary.d.ts | 25 +++++++------- tests/baselines/reference/api/typescript.d.ts | 25 +++++++------- .../templateLiteralTypes4.errors.txt | 10 ++++++ .../reference/templateLiteralTypes4.js | 17 ++++++++++ .../reference/templateLiteralTypes4.symbols | 33 +++++++++++++++++++ .../reference/templateLiteralTypes4.types | 32 ++++++++++++++++++ .../types/literal/templateLiteralTypes4.ts | 10 ++++++ 9 files changed, 145 insertions(+), 37 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b9ca23f74b51b..b5b4254126d7d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22771,9 +22771,12 @@ namespace ts { } if (sourceTypes) { + const savedPriority = priority; + priority |= InferencePriority.TemplateLiteralPlaceholder; for (const source of sourceTypes) { inferFromTypes(source, target); } + priority = savedPriority; } else { inferFromTypes(source, target); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 6becb6813eac6..51f00b0d40418 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5858,19 +5858,20 @@ namespace ts { export const enum InferencePriority { NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type - SpeculativeTuple = 1 << 1, // Speculative tuple inference - SubstituteSource = 1 << 2, // Source of inference originated within a substitution type's substitute - HomomorphicMappedType = 1 << 3, // Reverse inference for homomorphic mapped type - PartialHomomorphicMappedType = 1 << 4, // Partial reverse inference for homomorphic mapped type - MappedTypeConstraint = 1 << 5, // Reverse inference for mapped type - ContravariantConditional = 1 << 6, // Conditional type in contravariant position - ReturnType = 1 << 7, // Inference made from return type of generic function - LiteralKeyof = 1 << 8, // Inference made from a string literal to a keyof T - NoConstraints = 1 << 9, // Don't infer from constraints of instantiable types - AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences - MaxValue = 1 << 11, // Seed for inference priority tracking - - PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates + TemplateLiteralPlaceholder = 1 << 1, // Inference to a template literal type placeholder + SpeculativeTuple = 1 << 2, // Speculative tuple inference + SubstituteSource = 1 << 3, // Source of inference originated within a substitution type's substitute + HomomorphicMappedType = 1 << 4, // Reverse inference for homomorphic mapped type + PartialHomomorphicMappedType = 1 << 5, // Partial reverse inference for homomorphic mapped type + MappedTypeConstraint = 1 << 6, // Reverse inference for mapped type + ContravariantConditional = 1 << 7, // Conditional type in contravariant position + ReturnType = 1 << 8, // Inference made from return type of generic function + LiteralKeyof = 1 << 9, // Inference made from a string literal to a keyof T + NoConstraints = 1 << 10, // Don't infer from constraints of instantiable types + AlwaysStrict = 1 << 11, // Always use strict rules for contravariant inferences + MaxValue = 1 << 12, // Seed for inference priority tracking + + PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof | TemplateLiteralPlaceholder, // These priorities imply that the resulting type should be a combination of all candidates Circularity = -1, // Inference circularity (value less than all other priorities) } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 9f6634bcfa393..c7e45a8a33828 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2823,18 +2823,19 @@ declare namespace ts { } export enum InferencePriority { NakedTypeVariable = 1, - SpeculativeTuple = 2, - SubstituteSource = 4, - HomomorphicMappedType = 8, - PartialHomomorphicMappedType = 16, - MappedTypeConstraint = 32, - ContravariantConditional = 64, - ReturnType = 128, - LiteralKeyof = 256, - NoConstraints = 512, - AlwaysStrict = 1024, - MaxValue = 2048, - PriorityImpliesCombination = 416, + TemplateLiteralPlaceholder = 2, + SpeculativeTuple = 4, + SubstituteSource = 8, + HomomorphicMappedType = 16, + PartialHomomorphicMappedType = 32, + MappedTypeConstraint = 64, + ContravariantConditional = 128, + ReturnType = 256, + LiteralKeyof = 512, + NoConstraints = 1024, + AlwaysStrict = 2048, + MaxValue = 4096, + PriorityImpliesCombination = 834, Circularity = -1 } /** @deprecated Use FileExtensionInfo instead. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2219a924d47e7..93c7adc1c6982 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2823,18 +2823,19 @@ declare namespace ts { } export enum InferencePriority { NakedTypeVariable = 1, - SpeculativeTuple = 2, - SubstituteSource = 4, - HomomorphicMappedType = 8, - PartialHomomorphicMappedType = 16, - MappedTypeConstraint = 32, - ContravariantConditional = 64, - ReturnType = 128, - LiteralKeyof = 256, - NoConstraints = 512, - AlwaysStrict = 1024, - MaxValue = 2048, - PriorityImpliesCombination = 416, + TemplateLiteralPlaceholder = 2, + SpeculativeTuple = 4, + SubstituteSource = 8, + HomomorphicMappedType = 16, + PartialHomomorphicMappedType = 32, + MappedTypeConstraint = 64, + ContravariantConditional = 128, + ReturnType = 256, + LiteralKeyof = 512, + NoConstraints = 1024, + AlwaysStrict = 2048, + MaxValue = 4096, + PriorityImpliesCombination = 834, Circularity = -1 } /** @deprecated Use FileExtensionInfo instead. */ diff --git a/tests/baselines/reference/templateLiteralTypes4.errors.txt b/tests/baselines/reference/templateLiteralTypes4.errors.txt index e92d5cafb6d3c..59fab826bdbbb 100644 --- a/tests/baselines/reference/templateLiteralTypes4.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes4.errors.txt @@ -104,4 +104,14 @@ tests/cases/conformance/types/literal/templateLiteralTypes4.ts(97,12): error TS2 p.setIndex(2, 3); // error, 2 is not a valid index ~ !!! error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. + + declare function f1(s: `**${T}**`): T; + f1("**123**"); // "123" | 123 + + declare function f2(s: `**${T}**`): T; + f2("**123**"); // "123" | 123n + + declare function f3(s: `**${T}**`): T; + f3("**true**"); // true | "true" + f3("**false**"); // false | "false" \ No newline at end of file diff --git a/tests/baselines/reference/templateLiteralTypes4.js b/tests/baselines/reference/templateLiteralTypes4.js index c3654864b1d70..9ffb51c86b34d 100644 --- a/tests/baselines/reference/templateLiteralTypes4.js +++ b/tests/baselines/reference/templateLiteralTypes4.js @@ -96,6 +96,16 @@ p.getIndex(2); // error, 2 is not a valid index p.setIndex(0, 0); // ok, 0 is a valid index p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index + +declare function f1(s: `**${T}**`): T; +f1("**123**"); // "123" | 123 + +declare function f2(s: `**${T}**`): T; +f2("**123**"); // "123" | 123n + +declare function f3(s: `**${T}**`): T; +f3("**true**"); // true | "true" +f3("**false**"); // false | "false" //// [templateLiteralTypes4.js] @@ -106,6 +116,10 @@ p.getIndex(2); // error, 2 is not a valid index p.setIndex(0, 0); // ok, 0 is a valid index p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index +f1("**123**"); // "123" | 123 +f2("**123**"); // "123" | 123n +f3("**true**"); // true | "true" +f3("**false**"); // false | "false" //// [templateLiteralTypes4.d.ts] @@ -180,3 +194,6 @@ declare type Point = TypedObject<[ } ]>; declare const p: Point; +declare function f1(s: `**${T}**`): T; +declare function f2(s: `**${T}**`): T; +declare function f3(s: `**${T}**`): T; diff --git a/tests/baselines/reference/templateLiteralTypes4.symbols b/tests/baselines/reference/templateLiteralTypes4.symbols index 58a08396f3828..53828f00ae02b 100644 --- a/tests/baselines/reference/templateLiteralTypes4.symbols +++ b/tests/baselines/reference/templateLiteralTypes4.symbols @@ -400,3 +400,36 @@ p.setIndex(2, 3); // error, 2 is not a valid index >p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) >setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +declare function f1(s: `**${T}**`): T; +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 96, 17)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 98, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 98, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 98, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 98, 20)) + +f1("**123**"); // "123" | 123 +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 96, 17)) + +declare function f2(s: `**${T}**`): T; +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 99, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 101, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 20)) + +f2("**123**"); // "123" | 123n +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 99, 14)) + +declare function f3(s: `**${T}**`): T; +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 102, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 104, 48)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 20)) + +f3("**true**"); // true | "true" +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 102, 14)) + +f3("**false**"); // false | "false" +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 102, 14)) + diff --git a/tests/baselines/reference/templateLiteralTypes4.types b/tests/baselines/reference/templateLiteralTypes4.types index e458ab1b4413f..7af27f6d50253 100644 --- a/tests/baselines/reference/templateLiteralTypes4.types +++ b/tests/baselines/reference/templateLiteralTypes4.types @@ -242,3 +242,35 @@ p.setIndex(2, 3); // error, 2 is not a valid index >2 : 2 >3 : 3 +declare function f1(s: `**${T}**`): T; +>f1 : (s: `**${T}**`) => T +>s : `**${T}**` + +f1("**123**"); // "123" | 123 +>f1("**123**") : "123" | 123 +>f1 : (s: `**${T}**`) => T +>"**123**" : "**123**" + +declare function f2(s: `**${T}**`): T; +>f2 : (s: `**${T}**`) => T +>s : `**${T}**` + +f2("**123**"); // "123" | 123n +>f2("**123**") : "123" | 123n +>f2 : (s: `**${T}**`) => T +>"**123**" : "**123**" + +declare function f3(s: `**${T}**`): T; +>f3 : (s: `**${T}**`) => T +>s : `**${T}**` + +f3("**true**"); // true | "true" +>f3("**true**") : true | "true" +>f3 : (s: `**${T}**`) => T +>"**true**" : "**true**" + +f3("**false**"); // false | "false" +>f3("**false**") : false | "false" +>f3 : (s: `**${T}**`) => T +>"**false**" : "**false**" + diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts index 5589725826088..c65c18954abde 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts @@ -98,3 +98,13 @@ p.getIndex(2); // error, 2 is not a valid index p.setIndex(0, 0); // ok, 0 is a valid index p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index + +declare function f1(s: `**${T}**`): T; +f1("**123**"); // "123" | 123 + +declare function f2(s: `**${T}**`): T; +f2("**123**"); // "123" | 123n + +declare function f3(s: `**${T}**`): T; +f3("**true**"); // true | "true" +f3("**false**"); // false | "false" From b897272663b6b652b215e8d06b6863db808be7dd Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 23 Mar 2022 21:37:12 -0700 Subject: [PATCH 04/10] Infer to a preferred constraint instead of a union --- src/compiler/checker.ts | 105 ++-- src/compiler/types.ts | 27 +- .../reference/api/tsserverlibrary.d.ts | 25 +- tests/baselines/reference/api/typescript.d.ts | 25 +- .../templateLiteralTypes4.errors.txt | 66 ++- .../reference/templateLiteralTypes4.js | 107 +++- .../reference/templateLiteralTypes4.symbols | 477 +++++++++++------- .../reference/templateLiteralTypes4.types | 132 +++-- .../types/literal/templateLiteralTypes4.ts | 63 ++- 9 files changed, 708 insertions(+), 319 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5b4254126d7d..8a345fb8c8748 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -263,6 +263,20 @@ namespace ts { VoidIsNonOptional = 1 << 1, } + const enum TemplateTypePlaceholderPriority { + Never, // lowest + Null, + Undefined, + BooleanLiterals, + Boolean, + BigIntLiterals, + BigInt, + NumberLiterals, + Number, + StringLiterals, + String, // highest + } + const enum IntrinsicTypeKind { Uppercase, Lowercase, @@ -22729,6 +22743,20 @@ namespace ts { } } + function getTemplateTypePlaceholderPriority(type: Type) { + return type.flags & TypeFlags.String ? TemplateTypePlaceholderPriority.String : + type.flags & TypeFlags.StringLiteral ? TemplateTypePlaceholderPriority.StringLiterals : + type.flags & TypeFlags.Number ? TemplateTypePlaceholderPriority.Number : + type.flags & TypeFlags.NumberLiteral ? TemplateTypePlaceholderPriority.NumberLiterals : + type.flags & TypeFlags.BigInt ? TemplateTypePlaceholderPriority.BigInt : + type.flags & TypeFlags.BigIntLiteral ? TemplateTypePlaceholderPriority.BigIntLiterals : + type.flags & TypeFlags.Boolean ? TemplateTypePlaceholderPriority.Boolean : + type.flags & TypeFlags.BooleanLiteral ? TemplateTypePlaceholderPriority.BooleanLiterals : + type.flags & TypeFlags.Undefined ? TemplateTypePlaceholderPriority.Undefined : + type.flags & TypeFlags.Null ? TemplateTypePlaceholderPriority.Null : + TemplateTypePlaceholderPriority.Never; + } + function inferToTemplateLiteralType(source: Type, target: TemplateLiteralType) { const matches = inferTypesFromTemplateLiteralType(source, target); const types = target.types; @@ -22745,42 +22773,61 @@ namespace ts { // If we are inferring from a string literal type to a type variable whose constraint includes one of the // allowed template literal placeholder types, infer from a literal type corresponding to the constraint. - let sourceTypes: Type[] | undefined; if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.TypeVariable) { const inferenceContext = getInferenceInfoForType(target); - const constraint = inferenceContext ? getConstraintOfTypeParameter(inferenceContext.typeParameter) : undefined; - if (constraint) { - const str = (source as StringLiteralType).value; - const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint]; - for (const constraintType of constraintTypes) { - const sourceType = - constraintType.flags & TypeFlags.StringLike ? source : - constraintType.flags & TypeFlags.NumberLike && isValidNumberString(str, /*roundTripOnly*/ true) ? getNumberLiteralType(+str) : - constraintType.flags & TypeFlags.BigIntLike && isValidBigIntString(str, /*roundTripOnly*/ true) ? parseBigIntLiteralType(str) : - constraintType.flags & TypeFlags.BooleanLike && str === trueType.intrinsicName ? trueType : - constraintType.flags & TypeFlags.BooleanLike && str === falseType.intrinsicName ? falseType : - constraintType.flags & TypeFlags.Null && str === nullType.intrinsicName ? nullType : - constraintType.flags & TypeFlags.Undefined && str === undefinedType.intrinsicName ? undefinedType : - undefined; - if (sourceType) { - sourceTypes ??= []; - sourceTypes.push(sourceType); + const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined; + if (constraint && !isTypeAny(constraint)) { + let allTypeFlags: TypeFlags = 0; + forEachType(constraint, t => { allTypeFlags |= t.flags; }); + + // If the constraint contains `string`, we don't need to look for a more preferred type + if (!(allTypeFlags & TypeFlags.String)) { + const str = (source as StringLiteralType).value; + + // If the type contains `number` or a number literal and the string isn't a valid number, exclude numbers + if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) { + allTypeFlags &= ~TypeFlags.NumberLike; + } + + // If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints + if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) { + allTypeFlags &= ~TypeFlags.BigIntLike; + } + + // for each type in the constraint, find the highest priority matching type + let matchingType: Type | undefined; + let matchingTypePriority = TemplateTypePlaceholderPriority.Never; + forEachType(constraint, t => { + if (t.flags & allTypeFlags) { + const typePriority = getTemplateTypePlaceholderPriority(t); + if (typePriority > matchingTypePriority) { + const newMatchingType = + t.flags & TypeFlags.String ? source : + t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above. + t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above. + t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType : + t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t : + t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t : + t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t : + t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t : + undefined; + if (newMatchingType) { + matchingType = newMatchingType; + matchingTypePriority = typePriority; + } + } + } + }); + + if (matchingType) { + inferFromTypes(matchingType, target); + continue; } } } } - if (sourceTypes) { - const savedPriority = priority; - priority |= InferencePriority.TemplateLiteralPlaceholder; - for (const source of sourceTypes) { - inferFromTypes(source, target); - } - priority = savedPriority; - } - else { - inferFromTypes(source, target); - } + inferFromTypes(source, target); } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 51f00b0d40418..5dd8bf9f4a158 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5858,20 +5858,19 @@ namespace ts { export const enum InferencePriority { NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type - TemplateLiteralPlaceholder = 1 << 1, // Inference to a template literal type placeholder - SpeculativeTuple = 1 << 2, // Speculative tuple inference - SubstituteSource = 1 << 3, // Source of inference originated within a substitution type's substitute - HomomorphicMappedType = 1 << 4, // Reverse inference for homomorphic mapped type - PartialHomomorphicMappedType = 1 << 5, // Partial reverse inference for homomorphic mapped type - MappedTypeConstraint = 1 << 6, // Reverse inference for mapped type - ContravariantConditional = 1 << 7, // Conditional type in contravariant position - ReturnType = 1 << 8, // Inference made from return type of generic function - LiteralKeyof = 1 << 9, // Inference made from a string literal to a keyof T - NoConstraints = 1 << 10, // Don't infer from constraints of instantiable types - AlwaysStrict = 1 << 11, // Always use strict rules for contravariant inferences - MaxValue = 1 << 12, // Seed for inference priority tracking - - PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof | TemplateLiteralPlaceholder, // These priorities imply that the resulting type should be a combination of all candidates + SpeculativeTuple = 1 << 1, // Speculative tuple inference + SubstituteSource = 1 << 2, // Source of inference originated within a substitution type's substitute + HomomorphicMappedType = 1 << 3, // Reverse inference for homomorphic mapped type + PartialHomomorphicMappedType = 1 << 4, // Partial reverse inference for homomorphic mapped type + MappedTypeConstraint = 1 << 5, // Reverse inference for mapped type + ContravariantConditional = 1 << 6, // Conditional type in contravariant position + ReturnType = 1 << 7, // Inference made from return type of generic function + LiteralKeyof = 1 << 8, // Inference made from a string literal to a keyof T + NoConstraints = 1 << 9, // Don't infer from constraints of instantiable types + AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences + MaxValue = 1 << 11, // Seed for inference priority tracking + + PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates Circularity = -1, // Inference circularity (value less than all other priorities) } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c7e45a8a33828..9f6634bcfa393 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2823,19 +2823,18 @@ declare namespace ts { } export enum InferencePriority { NakedTypeVariable = 1, - TemplateLiteralPlaceholder = 2, - SpeculativeTuple = 4, - SubstituteSource = 8, - HomomorphicMappedType = 16, - PartialHomomorphicMappedType = 32, - MappedTypeConstraint = 64, - ContravariantConditional = 128, - ReturnType = 256, - LiteralKeyof = 512, - NoConstraints = 1024, - AlwaysStrict = 2048, - MaxValue = 4096, - PriorityImpliesCombination = 834, + SpeculativeTuple = 2, + SubstituteSource = 4, + HomomorphicMappedType = 8, + PartialHomomorphicMappedType = 16, + MappedTypeConstraint = 32, + ContravariantConditional = 64, + ReturnType = 128, + LiteralKeyof = 256, + NoConstraints = 512, + AlwaysStrict = 1024, + MaxValue = 2048, + PriorityImpliesCombination = 416, Circularity = -1 } /** @deprecated Use FileExtensionInfo instead. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 93c7adc1c6982..2219a924d47e7 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2823,19 +2823,18 @@ declare namespace ts { } export enum InferencePriority { NakedTypeVariable = 1, - TemplateLiteralPlaceholder = 2, - SpeculativeTuple = 4, - SubstituteSource = 8, - HomomorphicMappedType = 16, - PartialHomomorphicMappedType = 32, - MappedTypeConstraint = 64, - ContravariantConditional = 128, - ReturnType = 256, - LiteralKeyof = 512, - NoConstraints = 1024, - AlwaysStrict = 2048, - MaxValue = 4096, - PriorityImpliesCombination = 834, + SpeculativeTuple = 2, + SubstituteSource = 4, + HomomorphicMappedType = 8, + PartialHomomorphicMappedType = 16, + MappedTypeConstraint = 32, + ContravariantConditional = 64, + ReturnType = 128, + LiteralKeyof = 256, + NoConstraints = 512, + AlwaysStrict = 1024, + MaxValue = 2048, + PriorityImpliesCombination = 416, Circularity = -1 } /** @deprecated Use FileExtensionInfo instead. */ diff --git a/tests/baselines/reference/templateLiteralTypes4.errors.txt b/tests/baselines/reference/templateLiteralTypes4.errors.txt index 59fab826bdbbb..0dc6d991c9885 100644 --- a/tests/baselines/reference/templateLiteralTypes4.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes4.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(93,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(97,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(128,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(132,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. ==== tests/cases/conformance/types/literal/templateLiteralTypes4.ts (2 errors) ==== @@ -34,12 +34,47 @@ tests/cases/conformance/types/literal/templateLiteralTypes4.ts(97,12): error TS2 type T40 = "undefined" extends `${Is}` ? T : never; // undefined type T41 = "abcd" extends `${Is}` ? T : never; // never - type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n - type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 - type T52 = "true" extends `${Is}` ? T : never; // "true" | true - type T53 = "false" extends `${Is}` ? T : never; // "false" | false - type T54 = "null" extends `${Is}` ? T : never; // "null" | null - type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined + type T500 = "100" extends `${Is}` ? T : never; // "100" + type T501 = "100" extends `${Is}` ? T : never; // 100 + type T502 = "100" extends `${Is}` ? T : never; // 100n + type T503 = "100" extends `${Is}` ? T : never; // "100" + type T504 = "100" extends `${Is}` ? T : never; // 100 + + type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" + type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 + type T512 = "1.1" extends `${Is}` ? T : never; // never + + type T520 = "true" extends `${Is}` ? T : never; // "true" + type T521 = "true" extends `${Is}` ? T : never; // true + + type T530 = "false" extends `${Is}` ? T : never; // "false" + type T531 = "false" extends `${Is}` ? T : never; // false + + type T540 = "null" extends `${Is}` ? T : never; // "null" + type T541 = "null" extends `${Is}` ? T : never; // null + + type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" + type T551 = "undefined" extends `${Is}` ? T : never; // undefined + + type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n + type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number + + type ExtractPrimitives = + | T + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) + ; + + // Type writer doesn't show the union that is produced, so we use a helper type to verify constraints + type T570 = ExtractPrimitives<"100">; + type CheckT570 = Is<"100" | 100 | 100n, T570>; + + type T571 = ExtractPrimitives<"1.1">; + type CheckT571 = Is<"1.1" | 1.1, T571>; + + type T572 = ExtractPrimitives<"true">; + type CheckT572 = Is<"true" | true, T572>; type NumberFor = S extends `${Is}` ? N : never; type T60 = NumberFor<"100">; // 100 @@ -106,12 +141,15 @@ tests/cases/conformance/types/literal/templateLiteralTypes4.ts(97,12): error TS2 !!! error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. declare function f1(s: `**${T}**`): T; - f1("**123**"); // "123" | 123 + f1("**123**"); // "123" + + declare function f2(s: `**${T}**`): T; + f2("**123**"); // 123 - declare function f2(s: `**${T}**`): T; - f2("**123**"); // "123" | 123n + declare function f3(s: `**${T}**`): T; + f3("**123**"); // 123n - declare function f3(s: `**${T}**`): T; - f3("**true**"); // true | "true" - f3("**false**"); // false | "false" + declare function f4(s: `**${T}**`): T; + f4("**true**"); // true | "true" + f4("**false**"); // false | "false" \ No newline at end of file diff --git a/tests/baselines/reference/templateLiteralTypes4.js b/tests/baselines/reference/templateLiteralTypes4.js index 9ffb51c86b34d..ffea456c5d927 100644 --- a/tests/baselines/reference/templateLiteralTypes4.js +++ b/tests/baselines/reference/templateLiteralTypes4.js @@ -30,12 +30,47 @@ type T31 = "abcd" extends `${Is}` ? T : never; // never type T40 = "undefined" extends `${Is}` ? T : never; // undefined type T41 = "abcd" extends `${Is}` ? T : never; // never -type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n -type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 -type T52 = "true" extends `${Is}` ? T : never; // "true" | true -type T53 = "false" extends `${Is}` ? T : never; // "false" | false -type T54 = "null" extends `${Is}` ? T : never; // "null" | null -type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined +type T500 = "100" extends `${Is}` ? T : never; // "100" +type T501 = "100" extends `${Is}` ? T : never; // 100 +type T502 = "100" extends `${Is}` ? T : never; // 100n +type T503 = "100" extends `${Is}` ? T : never; // "100" +type T504 = "100" extends `${Is}` ? T : never; // 100 + +type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" +type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 +type T512 = "1.1" extends `${Is}` ? T : never; // never + +type T520 = "true" extends `${Is}` ? T : never; // "true" +type T521 = "true" extends `${Is}` ? T : never; // true + +type T530 = "false" extends `${Is}` ? T : never; // "false" +type T531 = "false" extends `${Is}` ? T : never; // false + +type T540 = "null" extends `${Is}` ? T : never; // "null" +type T541 = "null" extends `${Is}` ? T : never; // null + +type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" +type T551 = "undefined" extends `${Is}` ? T : never; // undefined + +type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n +type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number + +type ExtractPrimitives = + | T + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) + ; + +// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints +type T570 = ExtractPrimitives<"100">; +type CheckT570 = Is<"100" | 100 | 100n, T570>; + +type T571 = ExtractPrimitives<"1.1">; +type CheckT571 = Is<"1.1" | 1.1, T571>; + +type T572 = ExtractPrimitives<"true">; +type CheckT572 = Is<"true" | true, T572>; type NumberFor = S extends `${Is}` ? N : never; type T60 = NumberFor<"100">; // 100 @@ -98,14 +133,17 @@ p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index declare function f1(s: `**${T}**`): T; -f1("**123**"); // "123" | 123 +f1("**123**"); // "123" + +declare function f2(s: `**${T}**`): T; +f2("**123**"); // 123 -declare function f2(s: `**${T}**`): T; -f2("**123**"); // "123" | 123n +declare function f3(s: `**${T}**`): T; +f3("**123**"); // 123n -declare function f3(s: `**${T}**`): T; -f3("**true**"); // true | "true" -f3("**false**"); // false | "false" +declare function f4(s: `**${T}**`): T; +f4("**true**"); // true | "true" +f4("**false**"); // false | "false" //// [templateLiteralTypes4.js] @@ -116,10 +154,11 @@ p.getIndex(2); // error, 2 is not a valid index p.setIndex(0, 0); // ok, 0 is a valid index p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index -f1("**123**"); // "123" | 123 -f2("**123**"); // "123" | 123n -f3("**true**"); // true | "true" -f3("**false**"); // false | "false" +f1("**123**"); // "123" +f2("**123**"); // 123 +f3("**123**"); // 123n +f4("**true**"); // true | "true" +f4("**false**"); // false | "false" //// [templateLiteralTypes4.d.ts] @@ -148,12 +187,31 @@ declare type T30 = "null" extends `${Is}` ? T : never; declare type T31 = "abcd" extends `${Is}` ? T : never; declare type T40 = "undefined" extends `${Is}` ? T : never; declare type T41 = "abcd" extends `${Is}` ? T : never; -declare type T50 = "100" extends `${Is}` ? T : never; -declare type T51 = "1.1" extends `${Is}` ? T : never; -declare type T52 = "true" extends `${Is}` ? T : never; -declare type T53 = "false" extends `${Is}` ? T : never; -declare type T54 = "null" extends `${Is}` ? T : never; -declare type T55 = "undefined" extends `${Is}` ? T : never; +declare type T500 = "100" extends `${Is}` ? T : never; +declare type T501 = "100" extends `${Is}` ? T : never; +declare type T502 = "100" extends `${Is}` ? T : never; +declare type T503 = "100" extends `${Is}` ? T : never; +declare type T504 = "100" extends `${Is}` ? T : never; +declare type T510 = "1.1" extends `${Is}` ? T : never; +declare type T511 = "1.1" extends `${Is}` ? T : never; +declare type T512 = "1.1" extends `${Is}` ? T : never; +declare type T520 = "true" extends `${Is}` ? T : never; +declare type T521 = "true" extends `${Is}` ? T : never; +declare type T530 = "false" extends `${Is}` ? T : never; +declare type T531 = "false" extends `${Is}` ? T : never; +declare type T540 = "null" extends `${Is}` ? T : never; +declare type T541 = "null" extends `${Is}` ? T : never; +declare type T550 = "undefined" extends `${Is}` ? T : never; +declare type T551 = "undefined" extends `${Is}` ? T : never; +declare type T560 = "100000000000000000000000" extends `${Is}` ? T : never; +declare type T561 = "100000000000000000000000" extends `${Is}` ? T : never; +declare type ExtractPrimitives = T | (T extends `${Is}` ? U : never) | (T extends `${Is}` ? U : never) | (T extends `${Is}` ? U : never); +declare type T570 = ExtractPrimitives<"100">; +declare type CheckT570 = Is<"100" | 100 | 100n, T570>; +declare type T571 = ExtractPrimitives<"1.1">; +declare type CheckT571 = Is<"1.1" | 1.1, T571>; +declare type T572 = ExtractPrimitives<"true">; +declare type CheckT572 = Is<"true" | true, T572>; declare type NumberFor = S extends `${Is}` ? N : never; declare type T60 = NumberFor<"100">; declare type T61 = NumberFor; @@ -195,5 +253,6 @@ declare type Point = TypedObject<[ ]>; declare const p: Point; declare function f1(s: `**${T}**`): T; -declare function f2(s: `**${T}**`): T; -declare function f3(s: `**${T}**`): T; +declare function f2(s: `**${T}**`): T; +declare function f3(s: `**${T}**`): T; +declare function f4(s: `**${T}**`): T; diff --git a/tests/baselines/reference/templateLiteralTypes4.symbols b/tests/baselines/reference/templateLiteralTypes4.symbols index 53828f00ae02b..5cb2f226853eb 100644 --- a/tests/baselines/reference/templateLiteralTypes4.symbols +++ b/tests/baselines/reference/templateLiteralTypes4.symbols @@ -150,286 +150,423 @@ type T41 = "abcd" extends `${Is}` ? T : never; // never >T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 37)) >T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 37)) -type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n ->T50 : Symbol(T50, Decl(templateLiteralTypes4.ts, 29, 66)) +type T500 = "100" extends `${Is}` ? T : never; // "100" +>T500 : Symbol(T500, Decl(templateLiteralTypes4.ts, 29, 66)) >Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 36)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 37)) -type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 ->T51 : Symbol(T51, Decl(templateLiteralTypes4.ts, 31, 109)) +type T501 = "100" extends `${Is}` ? T : never; // 100 +>T501 : Symbol(T501, Decl(templateLiteralTypes4.ts, 31, 81)) >Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 36)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 37)) -type T52 = "true" extends `${Is}` ? T : never; // "true" | true ->T52 : Symbol(T52, Decl(templateLiteralTypes4.ts, 32, 109)) +type T502 = "100" extends `${Is}` ? T : never; // 100n +>T502 : Symbol(T502, Decl(templateLiteralTypes4.ts, 32, 72)) >Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) >T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 37)) >T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 37)) -type T53 = "false" extends `${Is}` ? T : never; // "false" | false ->T53 : Symbol(T53, Decl(templateLiteralTypes4.ts, 33, 110)) +type T503 = "100" extends `${Is}` ? T : never; // "100" +>T503 : Symbol(T503, Decl(templateLiteralTypes4.ts, 33, 63)) >Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 37)) -type T54 = "null" extends `${Is}` ? T : never; // "null" | null ->T54 : Symbol(T54, Decl(templateLiteralTypes4.ts, 34, 111)) +type T504 = "100" extends `${Is}` ? T : never; // 100 +>T504 : Symbol(T504, Decl(templateLiteralTypes4.ts, 34, 71)) >Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) >T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 37)) >T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 37)) -type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined ->T55 : Symbol(T55, Decl(templateLiteralTypes4.ts, 35, 110)) +type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" +>T510 : Symbol(T510, Decl(templateLiteralTypes4.ts, 35, 71)) >Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 42)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 37)) + +type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 +>T511 : Symbol(T511, Decl(templateLiteralTypes4.ts, 37, 81)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 38, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 38, 37)) + +type T512 = "1.1" extends `${Is}` ? T : never; // never +>T512 : Symbol(T512, Decl(templateLiteralTypes4.ts, 38, 72)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 37)) + +type T520 = "true" extends `${Is}` ? T : never; // "true" +>T520 : Symbol(T520, Decl(templateLiteralTypes4.ts, 39, 63)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 41, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 41, 38)) + +type T521 = "true" extends `${Is}` ? T : never; // true +>T521 : Symbol(T521, Decl(templateLiteralTypes4.ts, 41, 74)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 38)) + +type T530 = "false" extends `${Is}` ? T : never; // "false" +>T530 : Symbol(T530, Decl(templateLiteralTypes4.ts, 42, 65)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 44, 39)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 44, 39)) + +type T531 = "false" extends `${Is}` ? T : never; // false +>T531 : Symbol(T531, Decl(templateLiteralTypes4.ts, 44, 75)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 39)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 39)) + +type T540 = "null" extends `${Is}` ? T : never; // "null" +>T540 : Symbol(T540, Decl(templateLiteralTypes4.ts, 45, 66)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 47, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 47, 38)) + +type T541 = "null" extends `${Is}` ? T : never; // null +>T541 : Symbol(T541, Decl(templateLiteralTypes4.ts, 47, 71)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 38)) + +type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" +>T550 : Symbol(T550, Decl(templateLiteralTypes4.ts, 48, 71)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 50, 43)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 50, 43)) + +type T551 = "undefined" extends `${Is}` ? T : never; // undefined +>T551 : Symbol(T551, Decl(templateLiteralTypes4.ts, 50, 81)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 43)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 43)) + +type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n +>T560 : Symbol(T560, Decl(templateLiteralTypes4.ts, 51, 72)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 58)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 58)) + +type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number +>T561 : Symbol(T561, Decl(templateLiteralTypes4.ts, 53, 93)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 58)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 58)) + +type ExtractPrimitives = +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) + + | T +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) + + | (T extends `${Is}` ? U : never) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 28)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 28)) + + | (T extends `${Is}` ? U : never) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 59, 28)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 59, 28)) + + | (T extends `${Is}` ? U : never) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 60, 28)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 60, 28)) + + ; + +// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints +type T570 = ExtractPrimitives<"100">; +>T570 : Symbol(T570, Decl(templateLiteralTypes4.ts, 61, 5)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) + +type CheckT570 = Is<"100" | 100 | 100n, T570>; +>CheckT570 : Symbol(CheckT570, Decl(templateLiteralTypes4.ts, 64, 37)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T570 : Symbol(T570, Decl(templateLiteralTypes4.ts, 61, 5)) + +type T571 = ExtractPrimitives<"1.1">; +>T571 : Symbol(T571, Decl(templateLiteralTypes4.ts, 65, 46)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) + +type CheckT571 = Is<"1.1" | 1.1, T571>; +>CheckT571 : Symbol(CheckT571, Decl(templateLiteralTypes4.ts, 67, 37)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T571 : Symbol(T571, Decl(templateLiteralTypes4.ts, 65, 46)) + +type T572 = ExtractPrimitives<"true">; +>T572 : Symbol(T572, Decl(templateLiteralTypes4.ts, 68, 39)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) + +type CheckT572 = Is<"true" | true, T572>; +>CheckT572 : Symbol(CheckT572, Decl(templateLiteralTypes4.ts, 70, 38)) +>Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) +>T572 : Symbol(T572, Decl(templateLiteralTypes4.ts, 68, 39)) type NumberFor = S extends `${Is}` ? N : never; ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 38, 15)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 38, 15)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 73, 15)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 73, 15)) >Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 38, 56)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 38, 56)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 73, 56)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 73, 56)) type T60 = NumberFor<"100">; // 100 ->T60 : Symbol(T60, Decl(templateLiteralTypes4.ts, 38, 82)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) +>T60 : Symbol(T60, Decl(templateLiteralTypes4.ts, 73, 82)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) type T61 = NumberFor; // never ->T61 : Symbol(T61, Decl(templateLiteralTypes4.ts, 39, 28)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) +>T61 : Symbol(T61, Decl(templateLiteralTypes4.ts, 74, 28)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) type T62 = NumberFor; // never ->T62 : Symbol(T62, Decl(templateLiteralTypes4.ts, 40, 26)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) +>T62 : Symbol(T62, Decl(templateLiteralTypes4.ts, 75, 26)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) // example use case: interface FieldDefinition { ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) readonly name: string; ->name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 44, 27)) +>name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 79, 27)) readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; ->type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 45, 26)) +>type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 80, 26)) } type FieldType = ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 15)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 15)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 15)) T extends "f32" | "f64" ? bigint : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 15)) never; // Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectNamedMembers = { ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 52, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 55, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 87, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 90, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) [P in TDef[number]["name"]]: FieldType["type"]>; ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 56, 5)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 55, 29)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 91, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 90, 29)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 55, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 56, 66)) ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 56, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 90, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 91, 66)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 91, 5)) }; // Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectOrdinalMembers = { ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 57, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 60, 31)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 92, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 95, 31)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) [I in Extract]: FieldType["type"]>; ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 61, 5)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 96, 5)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 60, 31)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 95, 31)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 60, 31)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 61, 5)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 95, 31)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 96, 5)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) }; // Default members interface TypedObjectMembers { ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 62, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 97, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) // get/set a field by name get(key: K): FieldType["type"]>; ->get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 65, 71)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 67, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 67, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 67, 8)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 100, 71)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 102, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 102, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 102, 8)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 67, 82)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 67, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 102, 82)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 102, 8)) set(key: K, value: FieldType["type"]>): void; ->set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 67, 112)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 68, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 68, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 68, 8)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 68, 47)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 102, 112)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 103, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 103, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 103, 8)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 103, 47)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 68, 88)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 68, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 103, 88)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 103, 8)) // get/set a field by index getIndex>(index: I): FieldType["type"]>; ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 71, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 73, 1)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 71, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 71, 13)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 106, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 108, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 106, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 106, 13)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 71, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 106, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) setIndex>(index: I, value: FieldType["type"]>): void; ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 72, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 73, 1)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 72, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 72, 13)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 72, 49)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 47, 1)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 107, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 108, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 107, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 107, 13)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 107, 49)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 65, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 72, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 107, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) } // Use constrained `infer` in template literal to get ordinal indices as numbers: type IndicesOf = NumberFor>; // ordinal indices as number literals ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 73, 1)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 36, 115)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 108, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 111, 15)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 111, 15)) type TypedObject = ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 76, 56)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 41, 28)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 111, 56)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) & TypedObjectMembers ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 62, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 97, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) & TypedObjectNamedMembers ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 52, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 87, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) & TypedObjectOrdinalMembers; ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 57, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 78, 17)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 92, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) // NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type type Point = TypedObject<[ ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 81, 38)) ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 76, 56)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 116, 38)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 111, 56)) { name: "x", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 85, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 85, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 120, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 120, 16)) { name: "y", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 86, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 86, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 121, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 121, 16)) ]>; declare const p: Point; ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 81, 38)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 116, 38)) p.getIndex(0); // ok, 0 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) p.getIndex(1); // ok, 1 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) p.getIndex(2); // error, 2 is not a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 68, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) p.setIndex(0, 0); // ok, 0 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) p.setIndex(1, 0); // ok, 1 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) p.setIndex(2, 3); // error, 2 is not a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 89, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 71, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) declare function f1(s: `**${T}**`): T; ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 96, 17)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 98, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 98, 47)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 98, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 98, 20)) - -f1("**123**"); // "123" | 123 ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 96, 17)) - -declare function f2(s: `**${T}**`): T; ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 99, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 101, 47)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 20)) - -f2("**123**"); // "123" | 123n ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 99, 14)) - -declare function f3(s: `**${T}**`): T; ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 102, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 104, 48)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 20)) - -f3("**true**"); // true | "true" ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 102, 14)) - -f3("**false**"); // false | "false" ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 102, 14)) +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 131, 17)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 133, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 20)) + +f1("**123**"); // "123" +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 131, 17)) + +declare function f2(s: `**${T}**`): T; +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 134, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 136, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 136, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 136, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 136, 20)) + +f2("**123**"); // 123 +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 134, 14)) + +declare function f3(s: `**${T}**`): T; +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 137, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 139, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 139, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 139, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 139, 20)) + +f3("**123**"); // 123n +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 137, 14)) + +declare function f4(s: `**${T}**`): T; +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 140, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 142, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 142, 39)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 142, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 142, 20)) + +f4("**true**"); // true | "true" +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 140, 14)) + +f4("**false**"); // false | "false" +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 140, 14)) diff --git a/tests/baselines/reference/templateLiteralTypes4.types b/tests/baselines/reference/templateLiteralTypes4.types index 7af27f6d50253..8312715831b4d 100644 --- a/tests/baselines/reference/templateLiteralTypes4.types +++ b/tests/baselines/reference/templateLiteralTypes4.types @@ -76,30 +76,93 @@ type T40 = "undefined" extends `${Is}` ? T : never; // undef type T41 = "abcd" extends `${Is}` ? T : never; // never >T41 : never -type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n ->T50 : "100" | 100 | 100n ->null : null +type T500 = "100" extends `${Is}` ? T : never; // "100" +>T500 : "100" -type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 ->T51 : "1.1" | 1.1 ->null : null +type T501 = "100" extends `${Is}` ? T : never; // 100 +>T501 : 100 -type T52 = "true" extends `${Is}` ? T : never; // "true" | true ->T52 : true | "true" ->null : null +type T502 = "100" extends `${Is}` ? T : never; // 100n +>T502 : 100n + +type T503 = "100" extends `${Is}` ? T : never; // "100" +>T503 : "100" + +type T504 = "100" extends `${Is}` ? T : never; // 100 +>T504 : 100 + +type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" +>T510 : "1.1" + +type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 +>T511 : 1.1 -type T53 = "false" extends `${Is}` ? T : never; // "false" | false ->T53 : false | "false" +type T512 = "1.1" extends `${Is}` ? T : never; // never +>T512 : never + +type T520 = "true" extends `${Is}` ? T : never; // "true" +>T520 : "true" + +type T521 = "true" extends `${Is}` ? T : never; // true +>T521 : true + +type T530 = "false" extends `${Is}` ? T : never; // "false" +>T530 : "false" + +type T531 = "false" extends `${Is}` ? T : never; // false +>T531 : false + +type T540 = "null" extends `${Is}` ? T : never; // "null" +>T540 : "null" >null : null -type T54 = "null" extends `${Is}` ? T : never; // "null" | null ->T54 : "null" | null +type T541 = "null" extends `${Is}` ? T : never; // null +>T541 : "null" >null : null -type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined ->T55 : "undefined" | undefined +type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" +>T550 : "undefined" + +type T551 = "undefined" extends `${Is}` ? T : never; // undefined +>T551 : undefined + +type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n +>T560 : 100000000000000000000000n + +type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number +>T561 : number + +type ExtractPrimitives = +>ExtractPrimitives : ExtractPrimitives + + | T + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) >null : null + ; + +// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints +type T570 = ExtractPrimitives<"100">; +>T570 : T570 + +type CheckT570 = Is<"100" | 100 | 100n, T570>; +>CheckT570 : "100" | 100 | 100n + +type T571 = ExtractPrimitives<"1.1">; +>T571 : T571 + +type CheckT571 = Is<"1.1" | 1.1, T571>; +>CheckT571 : "1.1" | 1.1 + +type T572 = ExtractPrimitives<"true">; +>T572 : T572 + +type CheckT572 = Is<"true" | true, T572>; +>CheckT572 : true | "true" +>true : true + type NumberFor = S extends `${Is}` ? N : never; >NumberFor : NumberFor @@ -246,31 +309,40 @@ declare function f1(s: `**${T}**`): T; >f1 : (s: `**${T}**`) => T >s : `**${T}**` -f1("**123**"); // "123" | 123 ->f1("**123**") : "123" | 123 +f1("**123**"); // "123" +>f1("**123**") : "123" >f1 : (s: `**${T}**`) => T >"**123**" : "**123**" -declare function f2(s: `**${T}**`): T; ->f2 : (s: `**${T}**`) => T +declare function f2(s: `**${T}**`): T; +>f2 : (s: `**${T}**`) => T +>s : `**${T}**` + +f2("**123**"); // 123 +>f2("**123**") : 123 +>f2 : (s: `**${T}**`) => T +>"**123**" : "**123**" + +declare function f3(s: `**${T}**`): T; +>f3 : (s: `**${T}**`) => T >s : `**${T}**` -f2("**123**"); // "123" | 123n ->f2("**123**") : "123" | 123n ->f2 : (s: `**${T}**`) => T +f3("**123**"); // 123n +>f3("**123**") : 123n +>f3 : (s: `**${T}**`) => T >"**123**" : "**123**" -declare function f3(s: `**${T}**`): T; ->f3 : (s: `**${T}**`) => T +declare function f4(s: `**${T}**`): T; +>f4 : (s: `**${T}**`) => T >s : `**${T}**` -f3("**true**"); // true | "true" ->f3("**true**") : true | "true" ->f3 : (s: `**${T}**`) => T +f4("**true**"); // true | "true" +>f4("**true**") : true +>f4 : (s: `**${T}**`) => T >"**true**" : "**true**" -f3("**false**"); // false | "false" ->f3("**false**") : false | "false" ->f3 : (s: `**${T}**`) => T +f4("**false**"); // false | "false" +>f4("**false**") : false +>f4 : (s: `**${T}**`) => T >"**false**" : "**false**" diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts index c65c18954abde..cfd1fdb2c7109 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts @@ -1,4 +1,5 @@ // @strict: true +// @target: esnext // @declaration: true type Is = T; @@ -32,12 +33,47 @@ type T31 = "abcd" extends `${Is}` ? T : never; // never type T40 = "undefined" extends `${Is}` ? T : never; // undefined type T41 = "abcd" extends `${Is}` ? T : never; // never -type T50 = "100" extends `${Is}` ? T : never; // "100" | 100 | 100n -type T51 = "1.1" extends `${Is}` ? T : never; // "100" | 1.1 -type T52 = "true" extends `${Is}` ? T : never; // "true" | true -type T53 = "false" extends `${Is}` ? T : never; // "false" | false -type T54 = "null" extends `${Is}` ? T : never; // "null" | null -type T55 = "undefined" extends `${Is}` ? T : never; // "undefined" | undefined +type T500 = "100" extends `${Is}` ? T : never; // "100" +type T501 = "100" extends `${Is}` ? T : never; // 100 +type T502 = "100" extends `${Is}` ? T : never; // 100n +type T503 = "100" extends `${Is}` ? T : never; // "100" +type T504 = "100" extends `${Is}` ? T : never; // 100 + +type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" +type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 +type T512 = "1.1" extends `${Is}` ? T : never; // never + +type T520 = "true" extends `${Is}` ? T : never; // "true" +type T521 = "true" extends `${Is}` ? T : never; // true + +type T530 = "false" extends `${Is}` ? T : never; // "false" +type T531 = "false" extends `${Is}` ? T : never; // false + +type T540 = "null" extends `${Is}` ? T : never; // "null" +type T541 = "null" extends `${Is}` ? T : never; // null + +type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" +type T551 = "undefined" extends `${Is}` ? T : never; // undefined + +type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n +type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number + +type ExtractPrimitives = + | T + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) + | (T extends `${Is}` ? U : never) + ; + +// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints +type T570 = ExtractPrimitives<"100">; +type CheckT570 = Is<"100" | 100 | 100n, T570>; + +type T571 = ExtractPrimitives<"1.1">; +type CheckT571 = Is<"1.1" | 1.1, T571>; + +type T572 = ExtractPrimitives<"true">; +type CheckT572 = Is<"true" | true, T572>; type NumberFor = S extends `${Is}` ? N : never; type T60 = NumberFor<"100">; // 100 @@ -100,11 +136,14 @@ p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index declare function f1(s: `**${T}**`): T; -f1("**123**"); // "123" | 123 +f1("**123**"); // "123" + +declare function f2(s: `**${T}**`): T; +f2("**123**"); // 123 -declare function f2(s: `**${T}**`): T; -f2("**123**"); // "123" | 123n +declare function f3(s: `**${T}**`): T; +f3("**123**"); // 123n -declare function f3(s: `**${T}**`): T; -f3("**true**"); // true | "true" -f3("**false**"); // false | "false" +declare function f4(s: `**${T}**`): T; +f4("**true**"); // true | "true" +f4("**false**"); // false | "false" From 2f157415d4dfce866dd0f1be3997c928cfb0495c Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 23 Mar 2022 22:03:36 -0700 Subject: [PATCH 05/10] Add reduceType --- src/compiler/checker.ts | 52 ++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8a345fb8c8748..dfd8ca14866b9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22777,8 +22777,7 @@ namespace ts { const inferenceContext = getInferenceInfoForType(target); const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined; if (constraint && !isTypeAny(constraint)) { - let allTypeFlags: TypeFlags = 0; - forEachType(constraint, t => { allTypeFlags |= t.flags; }); + let allTypeFlags = reduceType(constraint, (flags, t) => flags | t.flags, 0 as TypeFlags); // If the constraint contains `string`, we don't need to look for a more preferred type if (!(allTypeFlags & TypeFlags.String)) { @@ -22788,38 +22787,27 @@ namespace ts { if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) { allTypeFlags &= ~TypeFlags.NumberLike; } - + // If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) { allTypeFlags &= ~TypeFlags.BigIntLike; } - + // for each type in the constraint, find the highest priority matching type - let matchingType: Type | undefined; - let matchingTypePriority = TemplateTypePlaceholderPriority.Never; - forEachType(constraint, t => { - if (t.flags & allTypeFlags) { - const typePriority = getTemplateTypePlaceholderPriority(t); - if (typePriority > matchingTypePriority) { - const newMatchingType = - t.flags & TypeFlags.String ? source : - t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above. - t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above. - t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType : - t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t : - t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t : - t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t : - t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t : - undefined; - if (newMatchingType) { - matchingType = newMatchingType; - matchingTypePriority = typePriority; - } - } - } - }); - - if (matchingType) { + const matchingType = reduceType(constraint, (matchingType, t) => + !(t.flags & allTypeFlags) || getTemplateTypePlaceholderPriority(t) <= getTemplateTypePlaceholderPriority(matchingType) ? matchingType : + t.flags & TypeFlags.String ? source : + t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above. + t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above. + t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType : + t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t : + t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t : + t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t : + t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t : + matchingType, + neverType as Type); + + if (!(matchingType.flags & TypeFlags.Never)) { inferFromTypes(matchingType, target); continue; } @@ -23835,6 +23823,12 @@ namespace ts { return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type); } + function reduceType(type: Type, f: (memo: T, t: Type) => T | undefined, initial: T): T; + function reduceType(type: Type, f: (memo: T | undefined, t: Type) => T | undefined): T | undefined; + function reduceType(type: Type, f: (memo: T | undefined, t: Type) => T | undefined, initial?: T | undefined): T | undefined { + return type.flags & TypeFlags.Union ? reduceLeft((type as UnionType).types, f, initial) : f(initial, type); + } + function someType(type: Type, f: (t: Type) => boolean): boolean { return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type); } From 06685cb060ecb21edb3f3dcd97ea5ce08e97e38f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 5 Apr 2022 16:02:01 -0700 Subject: [PATCH 06/10] Switch tests to use infer..extends --- .../templateLiteralTypes4.errors.txt | 132 ++- .../reference/templateLiteralTypes4.js | 220 +++-- .../reference/templateLiteralTypes4.symbols | 837 ++++++++---------- .../reference/templateLiteralTypes4.types | 112 +-- .../types/literal/templateLiteralTypes4.ts | 128 ++- 5 files changed, 659 insertions(+), 770 deletions(-) diff --git a/tests/baselines/reference/templateLiteralTypes4.errors.txt b/tests/baselines/reference/templateLiteralTypes4.errors.txt index 0dc6d991c9885..b515416e1b5b5 100644 --- a/tests/baselines/reference/templateLiteralTypes4.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes4.errors.txt @@ -1,82 +1,74 @@ -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(128,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(132,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(120,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(124,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. ==== tests/cases/conformance/types/literal/templateLiteralTypes4.ts (2 errors) ==== - type Is = T; - - type T0 = "100" extends `${Is}` ? N : never; // 100 - type T1 = "-100" extends `${Is}` ? N : never; // -100 - type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 - type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) - type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) - type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) - type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) - type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) - type T8 = "abcd" extends `${Is}` ? N : never; // never - - type T10 = "100" extends `${Is}` ? N : never; // 100n - type T11 = "-100" extends `${Is}` ? N : never; // -100n - type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) - type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) - type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) - type T15 = "1.1" extends `${Is}` ? N : never; // never - type T16 = "10e2" extends `${Is}` ? N : never; // never - type T17 = "abcd" extends `${Is}` ? N : never; // never - - type T20 = "true" extends `${Is}` ? T : never; // true - type T21 = "false" extends `${Is}` ? T : never; // false - type T22 = "abcd" extends `${Is}` ? T : never; // never - - type T30 = "null" extends `${Is}` ? T : never; // null - type T31 = "abcd" extends `${Is}` ? T : never; // never - - type T40 = "undefined" extends `${Is}` ? T : never; // undefined - type T41 = "abcd" extends `${Is}` ? T : never; // never - - type T500 = "100" extends `${Is}` ? T : never; // "100" - type T501 = "100" extends `${Is}` ? T : never; // 100 - type T502 = "100" extends `${Is}` ? T : never; // 100n - type T503 = "100" extends `${Is}` ? T : never; // "100" - type T504 = "100" extends `${Is}` ? T : never; // 100 - - type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" - type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 - type T512 = "1.1" extends `${Is}` ? T : never; // never - - type T520 = "true" extends `${Is}` ? T : never; // "true" - type T521 = "true" extends `${Is}` ? T : never; // true - - type T530 = "false" extends `${Is}` ? T : never; // "false" - type T531 = "false" extends `${Is}` ? T : never; // false - - type T540 = "null" extends `${Is}` ? T : never; // "null" - type T541 = "null" extends `${Is}` ? T : never; // null - - type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" - type T551 = "undefined" extends `${Is}` ? T : never; // undefined - - type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n - type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number + type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 + type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 + type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 + type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) + type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never + + type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n + type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n + type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) + type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) + type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) + type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never + type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never + type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never + + type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true + type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false + type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never + + type T30 = "null" extends `${infer T extends null}` ? T : never; // null + type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never + + type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined + type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never + + type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" + type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 + type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n + type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" + type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 + + type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" + type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 + type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never + + type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" + type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true + + type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" + type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false + + type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" + type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null + + type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" + type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined + + type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n + type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number type ExtractPrimitives = | T - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) + | (T extends `${infer U extends number}` ? U : never) + | (T extends `${infer U extends bigint}` ? U : never) + | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; - // Type writer doesn't show the union that is produced, so we use a helper type to verify constraints - type T570 = ExtractPrimitives<"100">; - type CheckT570 = Is<"100" | 100 | 100n, T570>; + type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n + type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 + type T572 = ExtractPrimitives<"true">; // "true" | true - type T571 = ExtractPrimitives<"1.1">; - type CheckT571 = Is<"1.1" | 1.1, T571>; - - type T572 = ExtractPrimitives<"true">; - type CheckT572 = Is<"true" | true, T572>; - - type NumberFor = S extends `${Is}` ? N : never; + type NumberFor = S extends `${infer N extends number}` ? N : never; type T60 = NumberFor<"100">; // 100 type T61 = NumberFor; // never type T62 = NumberFor; // never diff --git a/tests/baselines/reference/templateLiteralTypes4.js b/tests/baselines/reference/templateLiteralTypes4.js index ffea456c5d927..9211ea4ed832d 100644 --- a/tests/baselines/reference/templateLiteralTypes4.js +++ b/tests/baselines/reference/templateLiteralTypes4.js @@ -1,78 +1,70 @@ //// [templateLiteralTypes4.ts] -type Is = T; - -type T0 = "100" extends `${Is}` ? N : never; // 100 -type T1 = "-100" extends `${Is}` ? N : never; // -100 -type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 -type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) -type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) -type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) -type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) -type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) -type T8 = "abcd" extends `${Is}` ? N : never; // never - -type T10 = "100" extends `${Is}` ? N : never; // 100n -type T11 = "-100" extends `${Is}` ? N : never; // -100n -type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) -type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) -type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) -type T15 = "1.1" extends `${Is}` ? N : never; // never -type T16 = "10e2" extends `${Is}` ? N : never; // never -type T17 = "abcd" extends `${Is}` ? N : never; // never - -type T20 = "true" extends `${Is}` ? T : never; // true -type T21 = "false" extends `${Is}` ? T : never; // false -type T22 = "abcd" extends `${Is}` ? T : never; // never - -type T30 = "null" extends `${Is}` ? T : never; // null -type T31 = "abcd" extends `${Is}` ? T : never; // never - -type T40 = "undefined" extends `${Is}` ? T : never; // undefined -type T41 = "abcd" extends `${Is}` ? T : never; // never - -type T500 = "100" extends `${Is}` ? T : never; // "100" -type T501 = "100" extends `${Is}` ? T : never; // 100 -type T502 = "100" extends `${Is}` ? T : never; // 100n -type T503 = "100" extends `${Is}` ? T : never; // "100" -type T504 = "100" extends `${Is}` ? T : never; // 100 - -type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" -type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 -type T512 = "1.1" extends `${Is}` ? T : never; // never - -type T520 = "true" extends `${Is}` ? T : never; // "true" -type T521 = "true" extends `${Is}` ? T : never; // true - -type T530 = "false" extends `${Is}` ? T : never; // "false" -type T531 = "false" extends `${Is}` ? T : never; // false - -type T540 = "null" extends `${Is}` ? T : never; // "null" -type T541 = "null" extends `${Is}` ? T : never; // null - -type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" -type T551 = "undefined" extends `${Is}` ? T : never; // undefined - -type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n -type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number +type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 +type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 +type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 +type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) +type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never + +type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n +type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n +type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never +type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never +type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never + +type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true +type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false +type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never + +type T30 = "null" extends `${infer T extends null}` ? T : never; // null +type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never + +type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never + +type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" +type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 +type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n +type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" +type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 + +type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" +type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 +type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never + +type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" +type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true + +type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" +type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false + +type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" +type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null + +type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" +type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined + +type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n +type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number type ExtractPrimitives = | T - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) + | (T extends `${infer U extends number}` ? U : never) + | (T extends `${infer U extends bigint}` ? U : never) + | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; -// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints -type T570 = ExtractPrimitives<"100">; -type CheckT570 = Is<"100" | 100 | 100n, T570>; - -type T571 = ExtractPrimitives<"1.1">; -type CheckT571 = Is<"1.1" | 1.1, T571>; - -type T572 = ExtractPrimitives<"true">; -type CheckT572 = Is<"true" | true, T572>; +type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n +type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 +type T572 = ExtractPrimitives<"true">; // "true" | true -type NumberFor = S extends `${Is}` ? N : never; +type NumberFor = S extends `${infer N extends number}` ? N : never; type T60 = NumberFor<"100">; // 100 type T61 = NumberFor; // never type T62 = NumberFor; // never @@ -162,57 +154,53 @@ f4("**false**"); // false | "false" //// [templateLiteralTypes4.d.ts] -declare type Is = T; -declare type T0 = "100" extends `${Is}` ? N : never; -declare type T1 = "-100" extends `${Is}` ? N : never; -declare type T2 = "1.1" extends `${Is}` ? N : never; -declare type T3 = "8e-11" extends `${Is}` ? N : never; -declare type T4 = "0x10" extends `${Is}` ? N : never; -declare type T5 = "0o10" extends `${Is}` ? N : never; -declare type T6 = "0b10" extends `${Is}` ? N : never; -declare type T7 = "10e2" extends `${Is}` ? N : never; -declare type T8 = "abcd" extends `${Is}` ? N : never; -declare type T10 = "100" extends `${Is}` ? N : never; -declare type T11 = "-100" extends `${Is}` ? N : never; -declare type T12 = "0x10" extends `${Is}` ? N : never; -declare type T13 = "0o10" extends `${Is}` ? N : never; -declare type T14 = "0b10" extends `${Is}` ? N : never; -declare type T15 = "1.1" extends `${Is}` ? N : never; -declare type T16 = "10e2" extends `${Is}` ? N : never; -declare type T17 = "abcd" extends `${Is}` ? N : never; -declare type T20 = "true" extends `${Is}` ? T : never; -declare type T21 = "false" extends `${Is}` ? T : never; -declare type T22 = "abcd" extends `${Is}` ? T : never; -declare type T30 = "null" extends `${Is}` ? T : never; -declare type T31 = "abcd" extends `${Is}` ? T : never; -declare type T40 = "undefined" extends `${Is}` ? T : never; -declare type T41 = "abcd" extends `${Is}` ? T : never; -declare type T500 = "100" extends `${Is}` ? T : never; -declare type T501 = "100" extends `${Is}` ? T : never; -declare type T502 = "100" extends `${Is}` ? T : never; -declare type T503 = "100" extends `${Is}` ? T : never; -declare type T504 = "100" extends `${Is}` ? T : never; -declare type T510 = "1.1" extends `${Is}` ? T : never; -declare type T511 = "1.1" extends `${Is}` ? T : never; -declare type T512 = "1.1" extends `${Is}` ? T : never; -declare type T520 = "true" extends `${Is}` ? T : never; -declare type T521 = "true" extends `${Is}` ? T : never; -declare type T530 = "false" extends `${Is}` ? T : never; -declare type T531 = "false" extends `${Is}` ? T : never; -declare type T540 = "null" extends `${Is}` ? T : never; -declare type T541 = "null" extends `${Is}` ? T : never; -declare type T550 = "undefined" extends `${Is}` ? T : never; -declare type T551 = "undefined" extends `${Is}` ? T : never; -declare type T560 = "100000000000000000000000" extends `${Is}` ? T : never; -declare type T561 = "100000000000000000000000" extends `${Is}` ? T : never; -declare type ExtractPrimitives = T | (T extends `${Is}` ? U : never) | (T extends `${Is}` ? U : never) | (T extends `${Is}` ? U : never); +declare type T0 = "100" extends `${infer N extends number}` ? N : never; +declare type T1 = "-100" extends `${infer N extends number}` ? N : never; +declare type T2 = "1.1" extends `${infer N extends number}` ? N : never; +declare type T3 = "8e-11" extends `${infer N extends number}` ? N : never; +declare type T4 = "0x10" extends `${infer N extends number}` ? N : never; +declare type T5 = "0o10" extends `${infer N extends number}` ? N : never; +declare type T6 = "0b10" extends `${infer N extends number}` ? N : never; +declare type T7 = "10e2" extends `${infer N extends number}` ? N : never; +declare type T8 = "abcd" extends `${infer N extends number}` ? N : never; +declare type T10 = "100" extends `${infer N extends bigint}` ? N : never; +declare type T11 = "-100" extends `${infer N extends bigint}` ? N : never; +declare type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; +declare type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; +declare type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; +declare type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; +declare type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; +declare type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; +declare type T20 = "true" extends `${infer T extends boolean}` ? T : never; +declare type T21 = "false" extends `${infer T extends boolean}` ? T : never; +declare type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; +declare type T30 = "null" extends `${infer T extends null}` ? T : never; +declare type T31 = "abcd" extends `${infer T extends null}` ? T : never; +declare type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; +declare type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; +declare type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; +declare type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; +declare type T502 = "100" extends `${infer T extends bigint}` ? T : never; +declare type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; +declare type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; +declare type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; +declare type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; +declare type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; +declare type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; +declare type T521 = "true" extends `${infer T extends boolean}` ? T : never; +declare type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; +declare type T531 = "false" extends `${infer T extends boolean}` ? T : never; +declare type T540 = "null" extends `${infer T extends string | null}` ? T : never; +declare type T541 = "null" extends `${infer T extends string | null}` ? T : never; +declare type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; +declare type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; +declare type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; +declare type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; +declare type ExtractPrimitives = T | (T extends `${infer U extends number}` ? U : never) | (T extends `${infer U extends bigint}` ? U : never) | (T extends `${infer U extends boolean | null | undefined}` ? U : never); declare type T570 = ExtractPrimitives<"100">; -declare type CheckT570 = Is<"100" | 100 | 100n, T570>; declare type T571 = ExtractPrimitives<"1.1">; -declare type CheckT571 = Is<"1.1" | 1.1, T571>; declare type T572 = ExtractPrimitives<"true">; -declare type CheckT572 = Is<"true" | true, T572>; -declare type NumberFor = S extends `${Is}` ? N : never; +declare type NumberFor = S extends `${infer N extends number}` ? N : never; declare type T60 = NumberFor<"100">; declare type T61 = NumberFor; declare type T62 = NumberFor; diff --git a/tests/baselines/reference/templateLiteralTypes4.symbols b/tests/baselines/reference/templateLiteralTypes4.symbols index 5cb2f226853eb..f0cf16f403c4f 100644 --- a/tests/baselines/reference/templateLiteralTypes4.symbols +++ b/tests/baselines/reference/templateLiteralTypes4.symbols @@ -1,572 +1,503 @@ === tests/cases/conformance/types/literal/templateLiteralTypes4.ts === -type Is = T; ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 0, 8)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 0, 20)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 0, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 0, 8)) - -type T0 = "100" extends `${Is}` ? N : never; // 100 ->T0 : Symbol(T0, Decl(templateLiteralTypes4.ts, 0, 28)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 35)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 35)) - -type T1 = "-100" extends `${Is}` ? N : never; // -100 ->T1 : Symbol(T1, Decl(templateLiteralTypes4.ts, 2, 61)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 36)) - -type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 ->T2 : Symbol(T2, Decl(templateLiteralTypes4.ts, 3, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 35)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 35)) - -type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) ->T3 : Symbol(T3, Decl(templateLiteralTypes4.ts, 4, 61)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 37)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 37)) - -type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) ->T4 : Symbol(T4, Decl(templateLiteralTypes4.ts, 5, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 36)) - -type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) ->T5 : Symbol(T5, Decl(templateLiteralTypes4.ts, 6, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 36)) - -type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) ->T6 : Symbol(T6, Decl(templateLiteralTypes4.ts, 7, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 36)) - -type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) ->T7 : Symbol(T7, Decl(templateLiteralTypes4.ts, 8, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 36)) - -type T8 = "abcd" extends `${Is}` ? N : never; // never ->T8 : Symbol(T8, Decl(templateLiteralTypes4.ts, 9, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 36)) - -type T10 = "100" extends `${Is}` ? N : never; // 100n ->T10 : Symbol(T10, Decl(templateLiteralTypes4.ts, 10, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 36)) - -type T11 = "-100" extends `${Is}` ? N : never; // -100n ->T11 : Symbol(T11, Decl(templateLiteralTypes4.ts, 12, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 37)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 37)) - -type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) ->T12 : Symbol(T12, Decl(templateLiteralTypes4.ts, 13, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 37)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 37)) - -type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) ->T13 : Symbol(T13, Decl(templateLiteralTypes4.ts, 14, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 37)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 37)) - -type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) ->T14 : Symbol(T14, Decl(templateLiteralTypes4.ts, 15, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 37)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 37)) - -type T15 = "1.1" extends `${Is}` ? N : never; // never ->T15 : Symbol(T15, Decl(templateLiteralTypes4.ts, 16, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 36)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 36)) - -type T16 = "10e2" extends `${Is}` ? N : never; // never ->T16 : Symbol(T16, Decl(templateLiteralTypes4.ts, 17, 62)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 37)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 37)) - -type T17 = "abcd" extends `${Is}` ? N : never; // never ->T17 : Symbol(T17, Decl(templateLiteralTypes4.ts, 18, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 37)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 37)) - -type T20 = "true" extends `${Is}` ? T : never; // true ->T20 : Symbol(T20, Decl(templateLiteralTypes4.ts, 19, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 37)) - -type T21 = "false" extends `${Is}` ? T : never; // false ->T21 : Symbol(T21, Decl(templateLiteralTypes4.ts, 21, 64)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 38)) - -type T22 = "abcd" extends `${Is}` ? T : never; // never ->T22 : Symbol(T22, Decl(templateLiteralTypes4.ts, 22, 65)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 37)) - -type T30 = "null" extends `${Is}` ? T : never; // null ->T30 : Symbol(T30, Decl(templateLiteralTypes4.ts, 23, 64)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 25, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 25, 37)) - -type T31 = "abcd" extends `${Is}` ? T : never; // never ->T31 : Symbol(T31, Decl(templateLiteralTypes4.ts, 25, 61)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 37)) - -type T40 = "undefined" extends `${Is}` ? T : never; // undefined ->T40 : Symbol(T40, Decl(templateLiteralTypes4.ts, 26, 61)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 42)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 42)) - -type T41 = "abcd" extends `${Is}` ? T : never; // never ->T41 : Symbol(T41, Decl(templateLiteralTypes4.ts, 28, 71)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 37)) - -type T500 = "100" extends `${Is}` ? T : never; // "100" ->T500 : Symbol(T500, Decl(templateLiteralTypes4.ts, 29, 66)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 37)) - -type T501 = "100" extends `${Is}` ? T : never; // 100 ->T501 : Symbol(T501, Decl(templateLiteralTypes4.ts, 31, 81)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 37)) - -type T502 = "100" extends `${Is}` ? T : never; // 100n ->T502 : Symbol(T502, Decl(templateLiteralTypes4.ts, 32, 72)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 37)) - -type T503 = "100" extends `${Is}` ? T : never; // "100" ->T503 : Symbol(T503, Decl(templateLiteralTypes4.ts, 33, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 34, 37)) - -type T504 = "100" extends `${Is}` ? T : never; // 100 ->T504 : Symbol(T504, Decl(templateLiteralTypes4.ts, 34, 71)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 37)) - -type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" ->T510 : Symbol(T510, Decl(templateLiteralTypes4.ts, 35, 71)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 37)) - -type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 ->T511 : Symbol(T511, Decl(templateLiteralTypes4.ts, 37, 81)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 38, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 38, 37)) - -type T512 = "1.1" extends `${Is}` ? T : never; // never ->T512 : Symbol(T512, Decl(templateLiteralTypes4.ts, 38, 72)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 37)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 37)) - -type T520 = "true" extends `${Is}` ? T : never; // "true" ->T520 : Symbol(T520, Decl(templateLiteralTypes4.ts, 39, 63)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 41, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 41, 38)) - -type T521 = "true" extends `${Is}` ? T : never; // true ->T521 : Symbol(T521, Decl(templateLiteralTypes4.ts, 41, 74)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 38)) - -type T530 = "false" extends `${Is}` ? T : never; // "false" ->T530 : Symbol(T530, Decl(templateLiteralTypes4.ts, 42, 65)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 44, 39)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 44, 39)) - -type T531 = "false" extends `${Is}` ? T : never; // false ->T531 : Symbol(T531, Decl(templateLiteralTypes4.ts, 44, 75)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 39)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 39)) - -type T540 = "null" extends `${Is}` ? T : never; // "null" ->T540 : Symbol(T540, Decl(templateLiteralTypes4.ts, 45, 66)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 47, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 47, 38)) - -type T541 = "null" extends `${Is}` ? T : never; // null ->T541 : Symbol(T541, Decl(templateLiteralTypes4.ts, 47, 71)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 38)) - -type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" ->T550 : Symbol(T550, Decl(templateLiteralTypes4.ts, 48, 71)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 50, 43)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 50, 43)) - -type T551 = "undefined" extends `${Is}` ? T : never; // undefined ->T551 : Symbol(T551, Decl(templateLiteralTypes4.ts, 50, 81)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 43)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 43)) - -type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n ->T560 : Symbol(T560, Decl(templateLiteralTypes4.ts, 51, 72)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 58)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 58)) - -type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number ->T561 : Symbol(T561, Decl(templateLiteralTypes4.ts, 53, 93)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 58)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 58)) +type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 +>T0 : Symbol(T0, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 0, 32)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 0, 32)) + +type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 +>T1 : Symbol(T1, Decl(templateLiteralTypes4.ts, 0, 64)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 33)) + +type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 +>T2 : Symbol(T2, Decl(templateLiteralTypes4.ts, 1, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 32)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 32)) + +type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) +>T3 : Symbol(T3, Decl(templateLiteralTypes4.ts, 2, 64)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 34)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 34)) + +type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>T4 : Symbol(T4, Decl(templateLiteralTypes4.ts, 3, 66)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 33)) + +type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>T5 : Symbol(T5, Decl(templateLiteralTypes4.ts, 4, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 33)) + +type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>T6 : Symbol(T6, Decl(templateLiteralTypes4.ts, 5, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 33)) + +type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>T7 : Symbol(T7, Decl(templateLiteralTypes4.ts, 6, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 33)) + +type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never +>T8 : Symbol(T8, Decl(templateLiteralTypes4.ts, 7, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 33)) + +type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n +>T10 : Symbol(T10, Decl(templateLiteralTypes4.ts, 8, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 33)) + +type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n +>T11 : Symbol(T11, Decl(templateLiteralTypes4.ts, 10, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 11, 34)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 11, 34)) + +type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>T12 : Symbol(T12, Decl(templateLiteralTypes4.ts, 11, 66)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 34)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 34)) + +type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>T13 : Symbol(T13, Decl(templateLiteralTypes4.ts, 12, 66)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 34)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 34)) + +type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>T14 : Symbol(T14, Decl(templateLiteralTypes4.ts, 13, 66)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 34)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 34)) + +type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never +>T15 : Symbol(T15, Decl(templateLiteralTypes4.ts, 14, 66)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 33)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 33)) + +type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never +>T16 : Symbol(T16, Decl(templateLiteralTypes4.ts, 15, 65)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 34)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 34)) + +type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never +>T17 : Symbol(T17, Decl(templateLiteralTypes4.ts, 16, 66)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 34)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 34)) + +type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true +>T20 : Symbol(T20, Decl(templateLiteralTypes4.ts, 17, 66)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 19, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 19, 34)) + +type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false +>T21 : Symbol(T21, Decl(templateLiteralTypes4.ts, 19, 67)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 20, 35)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 20, 35)) + +type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never +>T22 : Symbol(T22, Decl(templateLiteralTypes4.ts, 20, 68)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 34)) + +type T30 = "null" extends `${infer T extends null}` ? T : never; // null +>T30 : Symbol(T30, Decl(templateLiteralTypes4.ts, 21, 67)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 34)) + +type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never +>T31 : Symbol(T31, Decl(templateLiteralTypes4.ts, 23, 64)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 34)) + +type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +>T40 : Symbol(T40, Decl(templateLiteralTypes4.ts, 24, 64)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 39)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 39)) + +type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never +>T41 : Symbol(T41, Decl(templateLiteralTypes4.ts, 26, 74)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 34)) + +type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" +>T500 : Symbol(T500, Decl(templateLiteralTypes4.ts, 27, 69)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 34)) + +type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 +>T501 : Symbol(T501, Decl(templateLiteralTypes4.ts, 29, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 30, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 30, 34)) + +type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n +>T502 : Symbol(T502, Decl(templateLiteralTypes4.ts, 30, 75)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 34)) + +type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" +>T503 : Symbol(T503, Decl(templateLiteralTypes4.ts, 31, 66)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 34)) + +type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 +>T504 : Symbol(T504, Decl(templateLiteralTypes4.ts, 32, 74)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 34)) + +type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" +>T510 : Symbol(T510, Decl(templateLiteralTypes4.ts, 33, 74)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 34)) + +type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 +>T511 : Symbol(T511, Decl(templateLiteralTypes4.ts, 35, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 34)) + +type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never +>T512 : Symbol(T512, Decl(templateLiteralTypes4.ts, 36, 75)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 34)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 34)) + +type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" +>T520 : Symbol(T520, Decl(templateLiteralTypes4.ts, 37, 66)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 35)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 35)) + +type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true +>T521 : Symbol(T521, Decl(templateLiteralTypes4.ts, 39, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 40, 35)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 40, 35)) + +type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" +>T530 : Symbol(T530, Decl(templateLiteralTypes4.ts, 40, 68)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 36)) + +type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false +>T531 : Symbol(T531, Decl(templateLiteralTypes4.ts, 42, 78)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 36)) + +type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" +>T540 : Symbol(T540, Decl(templateLiteralTypes4.ts, 43, 69)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 35)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 35)) + +type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null +>T541 : Symbol(T541, Decl(templateLiteralTypes4.ts, 45, 74)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 46, 35)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 46, 35)) + +type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" +>T550 : Symbol(T550, Decl(templateLiteralTypes4.ts, 46, 74)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 40)) + +type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +>T551 : Symbol(T551, Decl(templateLiteralTypes4.ts, 48, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 40)) + +type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n +>T560 : Symbol(T560, Decl(templateLiteralTypes4.ts, 49, 75)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 55)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 55)) + +type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number +>T561 : Symbol(T561, Decl(templateLiteralTypes4.ts, 51, 96)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 52, 55)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 52, 55)) type ExtractPrimitives = ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) | T ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) - - | (T extends `${Is}` ? U : never) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 28)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 28)) - - | (T extends `${Is}` ? U : never) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 59, 28)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 59, 28)) - - | (T extends `${Is}` ? U : never) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 23)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 60, 28)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 60, 28)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) + + | (T extends `${infer U extends number}` ? U : never) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 56, 25)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 56, 25)) + + | (T extends `${infer U extends bigint}` ? U : never) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 57, 25)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 57, 25)) + + | (T extends `${infer U extends boolean | null | undefined}` ? U : never) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 25)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 25)) ; -// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints -type T570 = ExtractPrimitives<"100">; ->T570 : Symbol(T570, Decl(templateLiteralTypes4.ts, 61, 5)) ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) - -type CheckT570 = Is<"100" | 100 | 100n, T570>; ->CheckT570 : Symbol(CheckT570, Decl(templateLiteralTypes4.ts, 64, 37)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T570 : Symbol(T570, Decl(templateLiteralTypes4.ts, 61, 5)) - -type T571 = ExtractPrimitives<"1.1">; ->T571 : Symbol(T571, Decl(templateLiteralTypes4.ts, 65, 46)) ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) - -type CheckT571 = Is<"1.1" | 1.1, T571>; ->CheckT571 : Symbol(CheckT571, Decl(templateLiteralTypes4.ts, 67, 37)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T571 : Symbol(T571, Decl(templateLiteralTypes4.ts, 65, 46)) - -type T572 = ExtractPrimitives<"true">; ->T572 : Symbol(T572, Decl(templateLiteralTypes4.ts, 68, 39)) ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 54, 84)) - -type CheckT572 = Is<"true" | true, T572>; ->CheckT572 : Symbol(CheckT572, Decl(templateLiteralTypes4.ts, 70, 38)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->T572 : Symbol(T572, Decl(templateLiteralTypes4.ts, 68, 39)) - -type NumberFor = S extends `${Is}` ? N : never; ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 73, 15)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 73, 15)) ->Is : Symbol(Is, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 73, 56)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 73, 56)) +type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n +>T570 : Symbol(T570, Decl(templateLiteralTypes4.ts, 59, 5)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) + +type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 +>T571 : Symbol(T571, Decl(templateLiteralTypes4.ts, 61, 37)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) + +type T572 = ExtractPrimitives<"true">; // "true" | true +>T572 : Symbol(T572, Decl(templateLiteralTypes4.ts, 62, 37)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) + +type NumberFor = S extends `${infer N extends number}` ? N : never; +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 65, 15)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 65, 15)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 65, 53)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 65, 53)) type T60 = NumberFor<"100">; // 100 ->T60 : Symbol(T60, Decl(templateLiteralTypes4.ts, 73, 82)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) +>T60 : Symbol(T60, Decl(templateLiteralTypes4.ts, 65, 85)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) type T61 = NumberFor; // never ->T61 : Symbol(T61, Decl(templateLiteralTypes4.ts, 74, 28)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) +>T61 : Symbol(T61, Decl(templateLiteralTypes4.ts, 66, 28)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) type T62 = NumberFor; // never ->T62 : Symbol(T62, Decl(templateLiteralTypes4.ts, 75, 26)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) +>T62 : Symbol(T62, Decl(templateLiteralTypes4.ts, 67, 26)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) // example use case: interface FieldDefinition { ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) readonly name: string; ->name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 79, 27)) +>name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 71, 27)) readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; ->type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 80, 26)) +>type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 72, 26)) } type FieldType = ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 15)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) T extends "f32" | "f64" ? bigint : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) never; // Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectNamedMembers = { ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 87, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 90, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 79, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 82, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) [P in TDef[number]["name"]]: FieldType["type"]>; ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 91, 5)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 90, 29)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 83, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 82, 29)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 90, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 91, 66)) ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 91, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 82, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 83, 66)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 83, 5)) }; // Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectOrdinalMembers = { ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 92, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 95, 31)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 84, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 87, 31)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) [I in Extract]: FieldType["type"]>; ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 96, 5)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 88, 5)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 95, 31)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 87, 31)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 95, 31)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 96, 5)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 87, 31)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 88, 5)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) }; // Default members interface TypedObjectMembers { ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 97, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 89, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) // get/set a field by name get(key: K): FieldType["type"]>; ->get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 100, 71)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 102, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 102, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 102, 8)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) +>get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 92, 71)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 94, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 94, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 94, 8)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 102, 82)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 102, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 94, 82)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 94, 8)) set(key: K, value: FieldType["type"]>): void; ->set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 102, 112)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 103, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 103, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 103, 8)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 103, 47)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) +>set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 94, 112)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 95, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 95, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 95, 8)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 95, 47)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 103, 88)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 103, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 95, 88)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 95, 8)) // get/set a field by index getIndex>(index: I): FieldType["type"]>; ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 106, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 108, 1)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 106, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 106, 13)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 98, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 100, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 98, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 98, 13)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 106, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 98, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) setIndex>(index: I, value: FieldType["type"]>): void; ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 107, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 108, 1)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 107, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 107, 13)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 107, 49)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 82, 1)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 99, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 100, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 99, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 99, 13)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 99, 49)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 100, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 107, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 99, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) } // Use constrained `infer` in template literal to get ordinal indices as numbers: type IndicesOf = NumberFor>; // ordinal indices as number literals ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 108, 1)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 111, 15)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 71, 41)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 100, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 103, 15)) +>NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 111, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 103, 15)) type TypedObject = ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 111, 56)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 76, 28)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 103, 56)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) & TypedObjectMembers ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 97, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 89, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) & TypedObjectNamedMembers ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 87, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 79, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) & TypedObjectOrdinalMembers; ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 92, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 113, 17)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 84, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) // NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type type Point = TypedObject<[ ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 116, 38)) ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 111, 56)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 108, 38)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 103, 56)) { name: "x", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 120, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 120, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 112, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 112, 16)) { name: "y", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 121, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 121, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 113, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 113, 16)) ]>; declare const p: Point; ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 116, 38)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 108, 38)) p.getIndex(0); // ok, 0 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) p.getIndex(1); // ok, 1 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) p.getIndex(2); // error, 2 is not a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 103, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) p.setIndex(0, 0); // ok, 0 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) p.setIndex(1, 0); // ok, 1 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) p.setIndex(2, 3); // error, 2 is not a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 124, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 106, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) declare function f1(s: `**${T}**`): T; ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 131, 17)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 133, 47)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 20)) +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 123, 17)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 125, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 20)) f1("**123**"); // "123" ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 131, 17)) +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 123, 17)) declare function f2(s: `**${T}**`): T; ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 134, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 136, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 136, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 136, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 136, 20)) +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 126, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 128, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 20)) f2("**123**"); // 123 ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 134, 14)) +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 126, 14)) declare function f3(s: `**${T}**`): T; ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 137, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 139, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 139, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 139, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 139, 20)) +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 129, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 131, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 131, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 131, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 131, 20)) f3("**123**"); // 123n ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 137, 14)) +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 129, 14)) declare function f4(s: `**${T}**`): T; ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 140, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 142, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 142, 39)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 142, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 142, 20)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 132, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 134, 39)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 20)) f4("**true**"); // true | "true" ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 140, 14)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 132, 14)) f4("**false**"); // false | "false" ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 140, 14)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 132, 14)) diff --git a/tests/baselines/reference/templateLiteralTypes4.types b/tests/baselines/reference/templateLiteralTypes4.types index 8312715831b4d..6cfbf5a010919 100644 --- a/tests/baselines/reference/templateLiteralTypes4.types +++ b/tests/baselines/reference/templateLiteralTypes4.types @@ -1,169 +1,155 @@ === tests/cases/conformance/types/literal/templateLiteralTypes4.ts === -type Is = T; ->Is : T - -type T0 = "100" extends `${Is}` ? N : never; // 100 +type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 >T0 : 100 -type T1 = "-100" extends `${Is}` ? N : never; // -100 +type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 >T1 : -100 -type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 +type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 >T2 : 1.1 -type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) +type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) >T3 : 8e-11 -type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) +type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) >T4 : number -type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) +type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) >T5 : number -type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) +type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) >T6 : number -type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) +type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) >T7 : number -type T8 = "abcd" extends `${Is}` ? N : never; // never +type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never >T8 : never -type T10 = "100" extends `${Is}` ? N : never; // 100n +type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n >T10 : 100n -type T11 = "-100" extends `${Is}` ? N : never; // -100n +type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n >T11 : -100n -type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) >T12 : bigint -type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) >T13 : bigint -type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) +type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) >T14 : bigint -type T15 = "1.1" extends `${Is}` ? N : never; // never +type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never >T15 : never -type T16 = "10e2" extends `${Is}` ? N : never; // never +type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never >T16 : never -type T17 = "abcd" extends `${Is}` ? N : never; // never +type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never >T17 : never -type T20 = "true" extends `${Is}` ? T : never; // true +type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true >T20 : true -type T21 = "false" extends `${Is}` ? T : never; // false +type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false >T21 : false -type T22 = "abcd" extends `${Is}` ? T : never; // never +type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never >T22 : never -type T30 = "null" extends `${Is}` ? T : never; // null +type T30 = "null" extends `${infer T extends null}` ? T : never; // null >T30 : null >null : null -type T31 = "abcd" extends `${Is}` ? T : never; // never +type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never >T31 : never >null : null -type T40 = "undefined" extends `${Is}` ? T : never; // undefined +type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined >T40 : undefined -type T41 = "abcd" extends `${Is}` ? T : never; // never +type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never >T41 : never -type T500 = "100" extends `${Is}` ? T : never; // "100" +type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" >T500 : "100" -type T501 = "100" extends `${Is}` ? T : never; // 100 +type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 >T501 : 100 -type T502 = "100" extends `${Is}` ? T : never; // 100n +type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n >T502 : 100n -type T503 = "100" extends `${Is}` ? T : never; // "100" +type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" >T503 : "100" -type T504 = "100" extends `${Is}` ? T : never; // 100 +type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 >T504 : 100 -type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" +type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" >T510 : "1.1" -type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 +type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 >T511 : 1.1 -type T512 = "1.1" extends `${Is}` ? T : never; // never +type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never >T512 : never -type T520 = "true" extends `${Is}` ? T : never; // "true" +type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" >T520 : "true" -type T521 = "true" extends `${Is}` ? T : never; // true +type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true >T521 : true -type T530 = "false" extends `${Is}` ? T : never; // "false" +type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" >T530 : "false" -type T531 = "false" extends `${Is}` ? T : never; // false +type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false >T531 : false -type T540 = "null" extends `${Is}` ? T : never; // "null" +type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" >T540 : "null" >null : null -type T541 = "null" extends `${Is}` ? T : never; // null +type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null >T541 : "null" >null : null -type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" +type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" >T550 : "undefined" -type T551 = "undefined" extends `${Is}` ? T : never; // undefined +type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined >T551 : undefined -type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n +type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n >T560 : 100000000000000000000000n -type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number +type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number >T561 : number type ExtractPrimitives = >ExtractPrimitives : ExtractPrimitives | T - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) + | (T extends `${infer U extends number}` ? U : never) + | (T extends `${infer U extends bigint}` ? U : never) + | (T extends `${infer U extends boolean | null | undefined}` ? U : never) >null : null ; -// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints -type T570 = ExtractPrimitives<"100">; +type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n >T570 : T570 -type CheckT570 = Is<"100" | 100 | 100n, T570>; ->CheckT570 : "100" | 100 | 100n - -type T571 = ExtractPrimitives<"1.1">; +type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 >T571 : T571 -type CheckT571 = Is<"1.1" | 1.1, T571>; ->CheckT571 : "1.1" | 1.1 - -type T572 = ExtractPrimitives<"true">; +type T572 = ExtractPrimitives<"true">; // "true" | true >T572 : T572 -type CheckT572 = Is<"true" | true, T572>; ->CheckT572 : true | "true" ->true : true - -type NumberFor = S extends `${Is}` ? N : never; +type NumberFor = S extends `${infer N extends number}` ? N : never; >NumberFor : NumberFor type T60 = NumberFor<"100">; // 100 diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts index cfd1fdb2c7109..e3228613dc8d8 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts @@ -2,80 +2,72 @@ // @target: esnext // @declaration: true -type Is = T; - -type T0 = "100" extends `${Is}` ? N : never; // 100 -type T1 = "-100" extends `${Is}` ? N : never; // -100 -type T2 = "1.1" extends `${Is}` ? N : never; // 1.1 -type T3 = "8e-11" extends `${Is}` ? N : never; // 8e-11 (0.00000000008) -type T4 = "0x10" extends `${Is}` ? N : never; // number (not round-trippable) -type T5 = "0o10" extends `${Is}` ? N : never; // number (not round-trippable) -type T6 = "0b10" extends `${Is}` ? N : never; // number (not round-trippable) -type T7 = "10e2" extends `${Is}` ? N : never; // number (not round-trippable) -type T8 = "abcd" extends `${Is}` ? N : never; // never - -type T10 = "100" extends `${Is}` ? N : never; // 100n -type T11 = "-100" extends `${Is}` ? N : never; // -100n -type T12 = "0x10" extends `${Is}` ? N : never; // bigint (not round-trippable) -type T13 = "0o10" extends `${Is}` ? N : never; // bigint (not round-trippable) -type T14 = "0b10" extends `${Is}` ? N : never; // bigint (not round-trippable) -type T15 = "1.1" extends `${Is}` ? N : never; // never -type T16 = "10e2" extends `${Is}` ? N : never; // never -type T17 = "abcd" extends `${Is}` ? N : never; // never - -type T20 = "true" extends `${Is}` ? T : never; // true -type T21 = "false" extends `${Is}` ? T : never; // false -type T22 = "abcd" extends `${Is}` ? T : never; // never - -type T30 = "null" extends `${Is}` ? T : never; // null -type T31 = "abcd" extends `${Is}` ? T : never; // never - -type T40 = "undefined" extends `${Is}` ? T : never; // undefined -type T41 = "abcd" extends `${Is}` ? T : never; // never - -type T500 = "100" extends `${Is}` ? T : never; // "100" -type T501 = "100" extends `${Is}` ? T : never; // 100 -type T502 = "100" extends `${Is}` ? T : never; // 100n -type T503 = "100" extends `${Is}` ? T : never; // "100" -type T504 = "100" extends `${Is}` ? T : never; // 100 - -type T510 = "1.1" extends `${Is}` ? T : never; // "1.1" -type T511 = "1.1" extends `${Is}` ? T : never; // 1.1 -type T512 = "1.1" extends `${Is}` ? T : never; // never - -type T520 = "true" extends `${Is}` ? T : never; // "true" -type T521 = "true" extends `${Is}` ? T : never; // true - -type T530 = "false" extends `${Is}` ? T : never; // "false" -type T531 = "false" extends `${Is}` ? T : never; // false - -type T540 = "null" extends `${Is}` ? T : never; // "null" -type T541 = "null" extends `${Is}` ? T : never; // null - -type T550 = "undefined" extends `${Is}` ? T : never; // "undefined" -type T551 = "undefined" extends `${Is}` ? T : never; // undefined - -type T560 = "100000000000000000000000" extends `${Is}` ? T : never; // 100000000000000000000000n -type T561 = "100000000000000000000000" extends `${Is}` ? T : never; // number +type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 +type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 +type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 +type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) +type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never + +type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n +type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n +type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never +type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never +type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never + +type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true +type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false +type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never + +type T30 = "null" extends `${infer T extends null}` ? T : never; // null +type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never + +type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never + +type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" +type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 +type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n +type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" +type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 + +type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" +type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 +type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never + +type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" +type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true + +type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" +type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false + +type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" +type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null + +type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" +type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined + +type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n +type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number type ExtractPrimitives = | T - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) - | (T extends `${Is}` ? U : never) + | (T extends `${infer U extends number}` ? U : never) + | (T extends `${infer U extends bigint}` ? U : never) + | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; -// Type writer doesn't show the union that is produced, so we use a helper type to verify constraints -type T570 = ExtractPrimitives<"100">; -type CheckT570 = Is<"100" | 100 | 100n, T570>; +type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n +type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 +type T572 = ExtractPrimitives<"true">; // "true" | true -type T571 = ExtractPrimitives<"1.1">; -type CheckT571 = Is<"1.1" | 1.1, T571>; - -type T572 = ExtractPrimitives<"true">; -type CheckT572 = Is<"true" | true, T572>; - -type NumberFor = S extends `${Is}` ? N : never; +type NumberFor = S extends `${infer N extends number}` ? N : never; type T60 = NumberFor<"100">; // 100 type T61 = NumberFor; // never type T62 = NumberFor; // never From 67d7ce5e92c168dbfb5337b3ce69d52e732310d2 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 6 Apr 2022 16:40:52 -0700 Subject: [PATCH 07/10] Add missing primitive constraint cases --- src/compiler/checker.ts | 19 +- .../templateLiteralTypes4.errors.txt | 307 ++++- .../reference/templateLiteralTypes4.js | 474 +++++-- .../reference/templateLiteralTypes4.symbols | 1187 +++++++++++------ .../reference/templateLiteralTypes4.types | 498 +++++-- .../types/literal/templateLiteralTypes4.ts | 303 ++++- 6 files changed, 2048 insertions(+), 740 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dfd8ca14866b9..a43ce7c036c86 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -265,15 +265,15 @@ namespace ts { const enum TemplateTypePlaceholderPriority { Never, // lowest - Null, - Undefined, - BooleanLiterals, + KeywordLiterals, // true | false | null | undefined Boolean, BigIntLiterals, BigInt, NumberLiterals, + Enums, Number, StringLiterals, + TemplateLiterals, String, // highest } @@ -22745,15 +22745,18 @@ namespace ts { function getTemplateTypePlaceholderPriority(type: Type) { return type.flags & TypeFlags.String ? TemplateTypePlaceholderPriority.String : + type.flags & TypeFlags.TemplateLiteral ? TemplateTypePlaceholderPriority.TemplateLiterals : + type.flags & TypeFlags.StringMapping ? TemplateTypePlaceholderPriority.StringLiterals : type.flags & TypeFlags.StringLiteral ? TemplateTypePlaceholderPriority.StringLiterals : type.flags & TypeFlags.Number ? TemplateTypePlaceholderPriority.Number : + type.flags & TypeFlags.Enum ? TemplateTypePlaceholderPriority.Enums : type.flags & TypeFlags.NumberLiteral ? TemplateTypePlaceholderPriority.NumberLiterals : type.flags & TypeFlags.BigInt ? TemplateTypePlaceholderPriority.BigInt : type.flags & TypeFlags.BigIntLiteral ? TemplateTypePlaceholderPriority.BigIntLiterals : type.flags & TypeFlags.Boolean ? TemplateTypePlaceholderPriority.Boolean : - type.flags & TypeFlags.BooleanLiteral ? TemplateTypePlaceholderPriority.BooleanLiterals : - type.flags & TypeFlags.Undefined ? TemplateTypePlaceholderPriority.Undefined : - type.flags & TypeFlags.Null ? TemplateTypePlaceholderPriority.Null : + type.flags & TypeFlags.BooleanLiteral ? TemplateTypePlaceholderPriority.KeywordLiterals : + type.flags & TypeFlags.Undefined ? TemplateTypePlaceholderPriority.KeywordLiterals : + type.flags & TypeFlags.Null ? TemplateTypePlaceholderPriority.KeywordLiterals : TemplateTypePlaceholderPriority.Never; } @@ -22797,7 +22800,9 @@ namespace ts { const matchingType = reduceType(constraint, (matchingType, t) => !(t.flags & allTypeFlags) || getTemplateTypePlaceholderPriority(t) <= getTemplateTypePlaceholderPriority(matchingType) ? matchingType : t.flags & TypeFlags.String ? source : - t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above. + t.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, t as TemplateLiteralType) ? source : + t.flags & TypeFlags.StringMapping && str === applyStringMapping(t.symbol, str) ? source : + t.flags & (TypeFlags.Number | TypeFlags.Enum) ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number and TypeFlags.Enum would have been excluded above. t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above. t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType : t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t : diff --git a/tests/baselines/reference/templateLiteralTypes4.errors.txt b/tests/baselines/reference/templateLiteralTypes4.errors.txt index b515416e1b5b5..afb05fc4b661b 100644 --- a/tests/baselines/reference/templateLiteralTypes4.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes4.errors.txt @@ -1,62 +1,228 @@ -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(120,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(124,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(294,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(298,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. ==== tests/cases/conformance/types/literal/templateLiteralTypes4.ts (2 errors) ==== - type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 - type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 - type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 - type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) - type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) - type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) - type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) - type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) - type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never - - type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n - type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n - type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) - type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) - type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) - type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never - type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never - type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never - - type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true - type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false - type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never - - type T30 = "null" extends `${infer T extends null}` ? T : never; // null - type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never - - type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined - type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never - - type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" - type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 - type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n - type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" - type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 - - type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" - type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 - type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never - - type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" - type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true - - type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" - type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false - - type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" - type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null - - type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" - type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined - - type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n - type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number + // infer from number + type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100 + type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100 + type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 + type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) + type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) + type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never + // infer from bigint + type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n + type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n + type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) + type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) + type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) + type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never + type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never + type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never + + // infer from boolean + type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true + type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false + type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never + + // infer from null + type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null + type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never + + // infer from undefined + type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined + type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never + + // infer from literal enums + const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" } + type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + + const enum NumberLiteralEnum { Zero, One } + type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero + + // infer from non-literal enums + const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One } + type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0 + + // infer using priority: + // string > template-literal > (string-literal | string-literal-enum) > + // number > enum > (number-literal | number-literal-enum) > + // bigint > bigint-literal > + // boolean > (boolean-literal | undefined | null) + + // #region string + // string > string-literal-enum + type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0" + + // string > number + type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0" + + // string > enum + type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0" + + // string > (number-literal | number-literal-enum) + type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0" + type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0" + + // string > bigint + type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0" + + // string > bigint-literal + type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0" + + // string > boolean + type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" + type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" + + // string > (boolean-literal | undefined | null) + type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true" + type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false" + type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" + type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null" + // #endregion string + + // #region template-literal + // template-literal > number + type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10" + + // template-literal > enum + type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10" + + // template-literal > (number-literal | number-literal-enum) + type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10" + type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10" + + // template-literal > bigint + type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10" + + // template-literal > bigint-literal + type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10" + + // template-literal > boolean + type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true" + type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false" + + // template-literal > (boolean-literal | undefined | null) + type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true" + type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false" + type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined" + type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null" + // #endregion template-literal + + // #region string-literal + // string-literal > number + type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0" + + // string-literal > enum + type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0" + + // string-literal > (number-literal | number-literal-enum) + type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0" + type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0" + + // string-literal > bigint + type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0" + + // string-literal > bigint-literal + type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0" + + // string-literal > boolean + type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true" + type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false" + + // string-literal > (boolean-literal | undefined | null) + type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true" + type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false" + type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined" + type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null" + // #endregion string-literal + + // #region string-literal-enum + // string-literal-enum > number + type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero + + // string-literal-enum > enum + type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + + // string-literal-enum > (number-literal | number-literal-enum) + type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero + type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + + // string-literal-enum > bigint + type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero + + // string-literal-enum > bigint-literal + type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero + + // string-literal-enum > boolean + type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True + type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False + + // string-literal-enum > (boolean-literal | undefined | null) + type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True + type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False + type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined + type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null + // #endregion string-literal-enum + + // #region number + // number > enum + type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0 + + // number > number-literal-enum + type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0 + + // number > bigint + type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0 + + // number > bigint-literal + type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0 + // #endregion number + + // #region enum + // enum > number-literal-enum + type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0 + + // enum > bigint + type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0 + + // enum > bigint-literal + type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0 + // #endregion enum + + // #region number-literal + // number-literal > bigint + type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0 + + // number-literal > bigint-literal + type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0 + // #endregion number-literal + + // #region number-literal-enum + // number-literal-enum > bigint + type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero + + // number-literal-enum > bigint-literal + type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero + // #endregion number-literal-enum + + // non-matchable constituents are excluded + type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0 + type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0 + type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n + type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n + type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n + + // infer to prefix from string + type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1 + type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string) + type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':') + + // can use union w/multiple branches to extract each possibility type ExtractPrimitives = | T | (T extends `${infer U extends number}` ? U : never) @@ -64,16 +230,27 @@ tests/cases/conformance/types/literal/templateLiteralTypes4.ts(124,12): error TS | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; - type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n - type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 - type T572 = ExtractPrimitives<"true">; // "true" | true + // .types tests here are worthless until #48578 is merged + type Check = void; + + type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n + type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 + type TExtract2 = ExtractPrimitives<"true">; // "true" | true - type NumberFor = S extends `${infer N extends number}` ? N : never; - type T60 = NumberFor<"100">; // 100 - type T61 = NumberFor; // never - type T62 = NumberFor; // never + type _ = [ + Check, + Check, + Check, + ]; + + + + // example use case (based on old TypedObjects proposal): + + // Use constrained `infer` in template literal to get ordinal indices as numbers: + type IndexFor = S extends `${infer N extends number}` ? N : never; + type IndicesOf = IndexFor>; // ordinal indices as number literals - // example use case: interface FieldDefinition { readonly name: string; readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; @@ -105,9 +282,6 @@ tests/cases/conformance/types/literal/templateLiteralTypes4.ts(124,12): error TS setIndex>(index: I, value: FieldType["type"]>): void; } - // Use constrained `infer` in template literal to get ordinal indices as numbers: - type IndicesOf = NumberFor>; // ordinal indices as number literals - type TypedObject = & TypedObjectMembers & TypedObjectNamedMembers @@ -132,6 +306,7 @@ tests/cases/conformance/types/literal/templateLiteralTypes4.ts(124,12): error TS ~ !!! error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. + // function inference declare function f1(s: `**${T}**`): T; f1("**123**"); // "123" diff --git a/tests/baselines/reference/templateLiteralTypes4.js b/tests/baselines/reference/templateLiteralTypes4.js index 9211ea4ed832d..2ab3e60f30c1b 100644 --- a/tests/baselines/reference/templateLiteralTypes4.js +++ b/tests/baselines/reference/templateLiteralTypes4.js @@ -1,58 +1,224 @@ //// [templateLiteralTypes4.ts] -type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 -type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 -type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 -type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) -type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never - -type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n -type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n -type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) -type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) -type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) -type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never -type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never -type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never - -type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true -type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false -type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never - -type T30 = "null" extends `${infer T extends null}` ? T : never; // null -type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never - -type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined -type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never - -type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" -type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 -type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n -type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" -type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 - -type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" -type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 -type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never - -type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" -type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true - -type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" -type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false - -type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" -type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null - -type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" -type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined - -type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n -type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number +// infer from number +type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100 +type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100 +type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 +type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) +type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never +// infer from bigint +type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n +type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n +type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never +type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never +type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never + +// infer from boolean +type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true +type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false +type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never + +// infer from null +type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null +type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never + +// infer from undefined +type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never + +// infer from literal enums +const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" } +type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + +const enum NumberLiteralEnum { Zero, One } +type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero + +// infer from non-literal enums +const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One } +type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0 + +// infer using priority: +// string > template-literal > (string-literal | string-literal-enum) > +// number > enum > (number-literal | number-literal-enum) > +// bigint > bigint-literal > +// boolean > (boolean-literal | undefined | null) + +// #region string +// string > string-literal-enum +type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0" + +// string > number +type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0" + +// string > enum +type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0" + +// string > (number-literal | number-literal-enum) +type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0" +type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0" + +// string > bigint +type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0" + +// string > bigint-literal +type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0" + +// string > boolean +type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" +type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" + +// string > (boolean-literal | undefined | null) +type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true" +type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false" +type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" +type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null" +// #endregion string + +// #region template-literal +// template-literal > number +type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10" + +// template-literal > enum +type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10" + +// template-literal > (number-literal | number-literal-enum) +type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10" +type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10" + +// template-literal > bigint +type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10" + +// template-literal > bigint-literal +type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10" + +// template-literal > boolean +type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true" +type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false" + +// template-literal > (boolean-literal | undefined | null) +type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true" +type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false" +type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined" +type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null" +// #endregion template-literal + +// #region string-literal +// string-literal > number +type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0" + +// string-literal > enum +type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0" + +// string-literal > (number-literal | number-literal-enum) +type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0" +type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0" + +// string-literal > bigint +type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0" + +// string-literal > bigint-literal +type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0" + +// string-literal > boolean +type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true" +type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false" + +// string-literal > (boolean-literal | undefined | null) +type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true" +type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false" +type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined" +type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null" +// #endregion string-literal + +// #region string-literal-enum +// string-literal-enum > number +type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > enum +type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > (number-literal | number-literal-enum) +type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero +type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > bigint +type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > bigint-literal +type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > boolean +type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True +type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False + +// string-literal-enum > (boolean-literal | undefined | null) +type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True +type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False +type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined +type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null +// #endregion string-literal-enum + +// #region number +// number > enum +type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0 + +// number > number-literal-enum +type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0 + +// number > bigint +type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0 + +// number > bigint-literal +type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0 +// #endregion number + +// #region enum +// enum > number-literal-enum +type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0 + +// enum > bigint +type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0 + +// enum > bigint-literal +type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0 +// #endregion enum + +// #region number-literal +// number-literal > bigint +type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0 + +// number-literal > bigint-literal +type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0 +// #endregion number-literal + +// #region number-literal-enum +// number-literal-enum > bigint +type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero + +// number-literal-enum > bigint-literal +type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero +// #endregion number-literal-enum + +// non-matchable constituents are excluded +type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0 +type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0 +type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n +type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n +type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n + +// infer to prefix from string +type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1 +type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string) +type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':') + +// can use union w/multiple branches to extract each possibility type ExtractPrimitives = | T | (T extends `${infer U extends number}` ? U : never) @@ -60,16 +226,27 @@ type ExtractPrimitives = | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; -type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n -type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 -type T572 = ExtractPrimitives<"true">; // "true" | true +// .types tests here are worthless until #48578 is merged +type Check = void; + +type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n +type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 +type TExtract2 = ExtractPrimitives<"true">; // "true" | true + +type _ = [ + Check, + Check, + Check, +]; + + -type NumberFor = S extends `${infer N extends number}` ? N : never; -type T60 = NumberFor<"100">; // 100 -type T61 = NumberFor; // never -type T62 = NumberFor; // never +// example use case (based on old TypedObjects proposal): + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndexFor = S extends `${infer N extends number}` ? N : never; +type IndicesOf = IndexFor>; // ordinal indices as number literals -// example use case: interface FieldDefinition { readonly name: string; readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; @@ -101,9 +278,6 @@ interface TypedObjectMembers { setIndex>(index: I, value: FieldType["type"]>): void; } -// Use constrained `infer` in template literal to get ordinal indices as numbers: -type IndicesOf = NumberFor>; // ordinal indices as number literals - type TypedObject = & TypedObjectMembers & TypedObjectNamedMembers @@ -124,6 +298,7 @@ p.setIndex(0, 0); // ok, 0 is a valid index p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index +// function inference declare function f1(s: `**${T}**`): T; f1("**123**"); // "123" @@ -154,56 +329,128 @@ f4("**false**"); // false | "false" //// [templateLiteralTypes4.d.ts] -declare type T0 = "100" extends `${infer N extends number}` ? N : never; -declare type T1 = "-100" extends `${infer N extends number}` ? N : never; -declare type T2 = "1.1" extends `${infer N extends number}` ? N : never; -declare type T3 = "8e-11" extends `${infer N extends number}` ? N : never; -declare type T4 = "0x10" extends `${infer N extends number}` ? N : never; -declare type T5 = "0o10" extends `${infer N extends number}` ? N : never; -declare type T6 = "0b10" extends `${infer N extends number}` ? N : never; -declare type T7 = "10e2" extends `${infer N extends number}` ? N : never; -declare type T8 = "abcd" extends `${infer N extends number}` ? N : never; -declare type T10 = "100" extends `${infer N extends bigint}` ? N : never; -declare type T11 = "-100" extends `${infer N extends bigint}` ? N : never; -declare type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; -declare type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; -declare type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; -declare type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; -declare type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; -declare type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; -declare type T20 = "true" extends `${infer T extends boolean}` ? T : never; -declare type T21 = "false" extends `${infer T extends boolean}` ? T : never; -declare type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; -declare type T30 = "null" extends `${infer T extends null}` ? T : never; -declare type T31 = "abcd" extends `${infer T extends null}` ? T : never; -declare type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; -declare type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; -declare type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; -declare type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; -declare type T502 = "100" extends `${infer T extends bigint}` ? T : never; -declare type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; -declare type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; -declare type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; -declare type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; -declare type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; -declare type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; -declare type T521 = "true" extends `${infer T extends boolean}` ? T : never; -declare type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; -declare type T531 = "false" extends `${infer T extends boolean}` ? T : never; -declare type T540 = "null" extends `${infer T extends string | null}` ? T : never; -declare type T541 = "null" extends `${infer T extends string | null}` ? T : never; -declare type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; -declare type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; -declare type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; -declare type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; +declare type TNumber0 = "100" extends `${infer N extends number}` ? N : never; +declare type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; +declare type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; +declare type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; +declare type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; +declare type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; +declare type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; +declare type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; +declare type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; +declare type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; +declare type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; +declare type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; +declare type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; +declare type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; +declare type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; +declare type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; +declare type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; +declare type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; +declare type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; +declare type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; +declare type TNull0 = "null" extends `${infer T extends null}` ? T : never; +declare type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; +declare type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; +declare type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; +declare const enum StringLiteralEnum { + Zero = "0", + True = "true", + False = "false", + Undefined = "undefined", + Null = "null" +} +declare type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; +declare const enum NumberLiteralEnum { + Zero = 0, + One = 1 +} +declare type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; +declare const enum NonLiteralEnum { + Zero = 0, + One = 1 +} +declare type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; +declare type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; +declare type PString01 = "0" extends `${infer T extends string | number}` ? T : never; +declare type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; +declare type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; +declare type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; +declare type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; +declare type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; +declare type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; +declare type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; +declare type PString09 = "true" extends `${infer T extends string | true}` ? T : never; +declare type PString10 = "false" extends `${infer T extends string | false}` ? T : never; +declare type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; +declare type PString12 = "null" extends `${infer T extends string | null}` ? T : never; +declare type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; +declare type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; +declare type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; +declare type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; +declare type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; +declare type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; +declare type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; +declare type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; +declare type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; +declare type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; +declare type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; +declare type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; +declare type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; +declare type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; +declare type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; +declare type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; +declare type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; +declare type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; +declare type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; +declare type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; +declare type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; +declare type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; +declare type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; +declare type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; +declare type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; +declare type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; +declare type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; +declare type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; +declare type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; +declare type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; +declare type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; +declare type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; +declare type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; +declare type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; +declare type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; +declare type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; +declare type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; +declare type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; +declare type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; +declare type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; +declare type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; +declare type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; +declare type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; +declare type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; +declare type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; +declare type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; +declare type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; +declare type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; +declare type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; +declare type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; +declare type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; +declare type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; +declare type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; +declare type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; +declare type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; declare type ExtractPrimitives = T | (T extends `${infer U extends number}` ? U : never) | (T extends `${infer U extends bigint}` ? U : never) | (T extends `${infer U extends boolean | null | undefined}` ? U : never); -declare type T570 = ExtractPrimitives<"100">; -declare type T571 = ExtractPrimitives<"1.1">; -declare type T572 = ExtractPrimitives<"true">; -declare type NumberFor = S extends `${infer N extends number}` ? N : never; -declare type T60 = NumberFor<"100">; -declare type T61 = NumberFor; -declare type T62 = NumberFor; +declare type Check = void; +declare type TExtract0 = ExtractPrimitives<"100">; +declare type TExtract1 = ExtractPrimitives<"1.1">; +declare type TExtract2 = ExtractPrimitives<"true">; +declare type _ = [ + Check, + Check, + Check +]; +declare type IndexFor = S extends `${infer N extends number}` ? N : never; +declare type IndicesOf = IndexFor>; interface FieldDefinition { readonly name: string; readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; @@ -227,7 +474,6 @@ interface TypedObjectMembers { getIndex>(index: I): FieldType["type"]>; setIndex>(index: I, value: FieldType["type"]>): void; } -declare type IndicesOf = NumberFor>; declare type TypedObject = TypedObjectMembers & TypedObjectNamedMembers & TypedObjectOrdinalMembers; declare type Point = TypedObject<[ { diff --git a/tests/baselines/reference/templateLiteralTypes4.symbols b/tests/baselines/reference/templateLiteralTypes4.symbols index f0cf16f403c4f..d4376a7aa1aac 100644 --- a/tests/baselines/reference/templateLiteralTypes4.symbols +++ b/tests/baselines/reference/templateLiteralTypes4.symbols @@ -1,503 +1,922 @@ === tests/cases/conformance/types/literal/templateLiteralTypes4.ts === -type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 ->T0 : Symbol(T0, Decl(templateLiteralTypes4.ts, 0, 0)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 0, 32)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 0, 32)) - -type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 ->T1 : Symbol(T1, Decl(templateLiteralTypes4.ts, 0, 64)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 33)) - -type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 ->T2 : Symbol(T2, Decl(templateLiteralTypes4.ts, 1, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 32)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 32)) - -type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) ->T3 : Symbol(T3, Decl(templateLiteralTypes4.ts, 2, 64)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 34)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 34)) - -type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T4 : Symbol(T4, Decl(templateLiteralTypes4.ts, 3, 66)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 33)) - -type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T5 : Symbol(T5, Decl(templateLiteralTypes4.ts, 4, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 33)) - -type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T6 : Symbol(T6, Decl(templateLiteralTypes4.ts, 5, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 33)) - -type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T7 : Symbol(T7, Decl(templateLiteralTypes4.ts, 6, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 33)) - -type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never ->T8 : Symbol(T8, Decl(templateLiteralTypes4.ts, 7, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 33)) - -type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n ->T10 : Symbol(T10, Decl(templateLiteralTypes4.ts, 8, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 10, 33)) - -type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n ->T11 : Symbol(T11, Decl(templateLiteralTypes4.ts, 10, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 11, 34)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 11, 34)) - -type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) ->T12 : Symbol(T12, Decl(templateLiteralTypes4.ts, 11, 66)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 34)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 34)) - -type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) ->T13 : Symbol(T13, Decl(templateLiteralTypes4.ts, 12, 66)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 34)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 34)) - -type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) ->T14 : Symbol(T14, Decl(templateLiteralTypes4.ts, 13, 66)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 34)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 34)) - -type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never ->T15 : Symbol(T15, Decl(templateLiteralTypes4.ts, 14, 66)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 33)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 33)) - -type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never ->T16 : Symbol(T16, Decl(templateLiteralTypes4.ts, 15, 65)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 34)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 34)) - -type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never ->T17 : Symbol(T17, Decl(templateLiteralTypes4.ts, 16, 66)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 34)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 34)) - -type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true ->T20 : Symbol(T20, Decl(templateLiteralTypes4.ts, 17, 66)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 19, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 19, 34)) - -type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false ->T21 : Symbol(T21, Decl(templateLiteralTypes4.ts, 19, 67)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 20, 35)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 20, 35)) - -type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never ->T22 : Symbol(T22, Decl(templateLiteralTypes4.ts, 20, 68)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 21, 34)) - -type T30 = "null" extends `${infer T extends null}` ? T : never; // null ->T30 : Symbol(T30, Decl(templateLiteralTypes4.ts, 21, 67)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 34)) - -type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never ->T31 : Symbol(T31, Decl(templateLiteralTypes4.ts, 23, 64)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 34)) - -type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined ->T40 : Symbol(T40, Decl(templateLiteralTypes4.ts, 24, 64)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 39)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 26, 39)) - -type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never ->T41 : Symbol(T41, Decl(templateLiteralTypes4.ts, 26, 74)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 34)) - -type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" ->T500 : Symbol(T500, Decl(templateLiteralTypes4.ts, 27, 69)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 29, 34)) - -type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 ->T501 : Symbol(T501, Decl(templateLiteralTypes4.ts, 29, 84)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 30, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 30, 34)) - -type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n ->T502 : Symbol(T502, Decl(templateLiteralTypes4.ts, 30, 75)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 34)) - -type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" ->T503 : Symbol(T503, Decl(templateLiteralTypes4.ts, 31, 66)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 34)) - -type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 ->T504 : Symbol(T504, Decl(templateLiteralTypes4.ts, 32, 74)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 33, 34)) - -type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" ->T510 : Symbol(T510, Decl(templateLiteralTypes4.ts, 33, 74)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 35, 34)) - -type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 ->T511 : Symbol(T511, Decl(templateLiteralTypes4.ts, 35, 84)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 34)) - -type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never ->T512 : Symbol(T512, Decl(templateLiteralTypes4.ts, 36, 75)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 34)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 37, 34)) - -type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" ->T520 : Symbol(T520, Decl(templateLiteralTypes4.ts, 37, 66)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 35)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 35)) - -type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true ->T521 : Symbol(T521, Decl(templateLiteralTypes4.ts, 39, 77)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 40, 35)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 40, 35)) - -type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" ->T530 : Symbol(T530, Decl(templateLiteralTypes4.ts, 40, 68)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 36)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 42, 36)) - -type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false ->T531 : Symbol(T531, Decl(templateLiteralTypes4.ts, 42, 78)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 36)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 36)) - -type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" ->T540 : Symbol(T540, Decl(templateLiteralTypes4.ts, 43, 69)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 35)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 45, 35)) - -type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null ->T541 : Symbol(T541, Decl(templateLiteralTypes4.ts, 45, 74)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 46, 35)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 46, 35)) - -type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" ->T550 : Symbol(T550, Decl(templateLiteralTypes4.ts, 46, 74)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 40)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 48, 40)) - -type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined ->T551 : Symbol(T551, Decl(templateLiteralTypes4.ts, 48, 84)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 40)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 49, 40)) - -type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n ->T560 : Symbol(T560, Decl(templateLiteralTypes4.ts, 49, 75)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 55)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 51, 55)) - -type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number ->T561 : Symbol(T561, Decl(templateLiteralTypes4.ts, 51, 96)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 52, 55)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 52, 55)) - +// infer from number +type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100 +>TNumber0 : Symbol(TNumber0, Decl(templateLiteralTypes4.ts, 0, 0)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 38)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 38)) + +type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100 +>TNumber1 : Symbol(TNumber1, Decl(templateLiteralTypes4.ts, 1, 70)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 39)) + +type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 +>TNumber2 : Symbol(TNumber2, Decl(templateLiteralTypes4.ts, 2, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 38)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 38)) + +type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) +>TNumber3 : Symbol(TNumber3, Decl(templateLiteralTypes4.ts, 3, 70)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 40)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 40)) + +type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber4 : Symbol(TNumber4, Decl(templateLiteralTypes4.ts, 4, 72)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 39)) + +type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber5 : Symbol(TNumber5, Decl(templateLiteralTypes4.ts, 5, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 39)) + +type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber6 : Symbol(TNumber6, Decl(templateLiteralTypes4.ts, 6, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 39)) + +type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber7 : Symbol(TNumber7, Decl(templateLiteralTypes4.ts, 7, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 39)) + +type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never +>TNumber8 : Symbol(TNumber8, Decl(templateLiteralTypes4.ts, 8, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 39)) + +// infer from bigint +type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n +>TBigInt0 : Symbol(TBigInt0, Decl(templateLiteralTypes4.ts, 9, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 38)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 38)) + +type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n +>TBigInt1 : Symbol(TBigInt1, Decl(templateLiteralTypes4.ts, 12, 70)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 39)) + +type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>TBigInt2 : Symbol(TBigInt2, Decl(templateLiteralTypes4.ts, 13, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 39)) + +type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>TBigInt3 : Symbol(TBigInt3, Decl(templateLiteralTypes4.ts, 14, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 39)) + +type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>TBigInt4 : Symbol(TBigInt4, Decl(templateLiteralTypes4.ts, 15, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 39)) + +type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never +>TBigInt5 : Symbol(TBigInt5, Decl(templateLiteralTypes4.ts, 16, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 38)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 38)) + +type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never +>TBigInt6 : Symbol(TBigInt6, Decl(templateLiteralTypes4.ts, 17, 70)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 39)) + +type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never +>TBigInt7 : Symbol(TBigInt7, Decl(templateLiteralTypes4.ts, 18, 71)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 39)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 39)) + +// infer from boolean +type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true +>TBoolean0 : Symbol(TBoolean0, Decl(templateLiteralTypes4.ts, 19, 71)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 40)) + +type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false +>TBoolean1 : Symbol(TBoolean1, Decl(templateLiteralTypes4.ts, 22, 73)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 41)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 41)) + +type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never +>TBoolean2 : Symbol(TBoolean2, Decl(templateLiteralTypes4.ts, 23, 74)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 40)) + +// infer from null +type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null +>TNull0 : Symbol(TNull0, Decl(templateLiteralTypes4.ts, 24, 73)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 37)) + +type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never +>TNull1 : Symbol(TNull1, Decl(templateLiteralTypes4.ts, 27, 67)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 37)) + +// infer from undefined +type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +>TUndefined0 : Symbol(TUndefined0, Decl(templateLiteralTypes4.ts, 28, 67)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 47)) + +type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never +>TUndefined1 : Symbol(TUndefined1, Decl(templateLiteralTypes4.ts, 31, 82)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 42)) + +// infer from literal enums +const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" } +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>Zero : Symbol(StringLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 35, 30)) +>True : Symbol(StringLiteralEnum.True, Decl(templateLiteralTypes4.ts, 35, 42)) +>False : Symbol(StringLiteralEnum.False, Decl(templateLiteralTypes4.ts, 35, 57)) +>Undefined : Symbol(StringLiteralEnum.Undefined, Decl(templateLiteralTypes4.ts, 35, 74)) +>Null : Symbol(StringLiteralEnum.Null, Decl(templateLiteralTypes4.ts, 35, 99)) + +type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero +>TStringLiteralEnum0 : Symbol(TStringLiteralEnum0, Decl(templateLiteralTypes4.ts, 35, 115)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 47)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 47)) + +const enum NumberLiteralEnum { Zero, One } +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>Zero : Symbol(NumberLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 38, 30)) +>One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36)) + +type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero +>TNumberLiteralEnum0 : Symbol(TNumberLiteralEnum0, Decl(templateLiteralTypes4.ts, 38, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 47)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 47)) + +// infer from non-literal enums +const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One } +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>Zero : Symbol(NonLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 42, 27)) +>NumberLiteralEnum.Zero : Symbol(NumberLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 38, 30)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>Zero : Symbol(NumberLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 38, 30)) +>One : Symbol(NonLiteralEnum.One, Decl(templateLiteralTypes4.ts, 42, 58)) +>NumberLiteralEnum.One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36)) + +type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0 +>TNonLiteralEnum0 : Symbol(TNonLiteralEnum0, Decl(templateLiteralTypes4.ts, 42, 88)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 44)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 44)) + +// infer using priority: +// string > template-literal > (string-literal | string-literal-enum) > +// number > enum > (number-literal | number-literal-enum) > +// bigint > bigint-literal > +// boolean > (boolean-literal | undefined | null) + +// #region string +// string > string-literal-enum +type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0" +>PString00 : Symbol(PString00, Decl(templateLiteralTypes4.ts, 43, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 37)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 37)) + +// string > number +type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0" +>PString01 : Symbol(PString01, Decl(templateLiteralTypes4.ts, 53, 89)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 37)) + +// string > enum +type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0" +>PString02 : Symbol(PString02, Decl(templateLiteralTypes4.ts, 56, 78)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 59, 37)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 59, 37)) + +// string > (number-literal | number-literal-enum) +type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0" +>PString03 : Symbol(PString03, Decl(templateLiteralTypes4.ts, 59, 86)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 62, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 62, 37)) + +type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0" +>PString04 : Symbol(PString04, Decl(templateLiteralTypes4.ts, 62, 73)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 63, 37)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 63, 37)) + +// string > bigint +type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0" +>PString05 : Symbol(PString05, Decl(templateLiteralTypes4.ts, 63, 89)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 66, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 66, 37)) + +// string > bigint-literal +type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0" +>PString06 : Symbol(PString06, Decl(templateLiteralTypes4.ts, 66, 78)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 69, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 69, 37)) + +// string > boolean +type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" +>PString07 : Symbol(PString07, Decl(templateLiteralTypes4.ts, 69, 74)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 72, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 72, 40)) + +type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" +>PString08 : Symbol(PString08, Decl(templateLiteralTypes4.ts, 72, 82)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 73, 41)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 73, 41)) + +// string > (boolean-literal | undefined | null) +type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true" +>PString09 : Symbol(PString09, Decl(templateLiteralTypes4.ts, 73, 83)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 40)) + +type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false" +>PString10 : Symbol(PString10, Decl(templateLiteralTypes4.ts, 76, 79)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 77, 41)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 77, 41)) + +type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" +>PString11 : Symbol(PString11, Decl(templateLiteralTypes4.ts, 77, 81)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 78, 45)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 78, 45)) + +type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null" +>PString12 : Symbol(PString12, Decl(templateLiteralTypes4.ts, 78, 89)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 79, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 79, 40)) + +// #endregion string + +// #region template-literal +// template-literal > number +type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10" +>PTemplate00 : Symbol(PTemplate00, Decl(templateLiteralTypes4.ts, 79, 79)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 40)) + +// template-literal > enum +type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10" +>PTemplate01 : Symbol(PTemplate01, Decl(templateLiteralTypes4.ts, 84, 87)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 87, 40)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 87, 40)) + +// template-literal > (number-literal | number-literal-enum) +type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10" +>PTemplate02 : Symbol(PTemplate02, Decl(templateLiteralTypes4.ts, 87, 95)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 90, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 90, 40)) + +type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10" +>PTemplate03 : Symbol(PTemplate03, Decl(templateLiteralTypes4.ts, 90, 83)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 91, 40)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 91, 40)) + +// template-literal > bigint +type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10" +>PTemplate04 : Symbol(PTemplate04, Decl(templateLiteralTypes4.ts, 91, 98)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 94, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 94, 40)) + +// template-literal > bigint-literal +type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10" +>PTemplate05 : Symbol(PTemplate05, Decl(templateLiteralTypes4.ts, 94, 87)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 97, 40)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 97, 40)) + +// template-literal > boolean +type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true" +>PTemplate06 : Symbol(PTemplate06, Decl(templateLiteralTypes4.ts, 97, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 100, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 100, 42)) + +type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false" +>PTemplate07 : Symbol(PTemplate07, Decl(templateLiteralTypes4.ts, 100, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 43)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 43)) + +// template-literal > (boolean-literal | undefined | null) +type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true" +>PTemplate08 : Symbol(PTemplate08, Decl(templateLiteralTypes4.ts, 101, 91)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 42)) + +type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false" +>PTemplate09 : Symbol(PTemplate09, Decl(templateLiteralTypes4.ts, 104, 92)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 105, 43)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 105, 43)) + +type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined" +>PTemplate10 : Symbol(PTemplate10, Decl(templateLiteralTypes4.ts, 105, 94)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 106, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 106, 47)) + +type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null" +>PTemplate11 : Symbol(PTemplate11, Decl(templateLiteralTypes4.ts, 106, 102)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 107, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 107, 42)) + +// #endregion template-literal + +// #region string-literal +// string-literal > number +type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0" +>PStringLiteral00 : Symbol(PStringLiteral00, Decl(templateLiteralTypes4.ts, 107, 92)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 112, 44)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 112, 44)) + +// string-literal > enum +type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0" +>PStringLiteral01 : Symbol(PStringLiteral01, Decl(templateLiteralTypes4.ts, 112, 82)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 115, 44)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 115, 44)) + +// string-literal > (number-literal | number-literal-enum) +type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0" +>PStringLiteral02 : Symbol(PStringLiteral02, Decl(templateLiteralTypes4.ts, 115, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 118, 44)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 118, 44)) + +type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0" +>PStringLiteral03 : Symbol(PStringLiteral03, Decl(templateLiteralTypes4.ts, 118, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 119, 44)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 119, 44)) + +// string-literal > bigint +type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0" +>PStringLiteral04 : Symbol(PStringLiteral04, Decl(templateLiteralTypes4.ts, 119, 93)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 122, 44)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 122, 44)) + +// string-literal > bigint-literal +type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0" +>PStringLiteral05 : Symbol(PStringLiteral05, Decl(templateLiteralTypes4.ts, 122, 82)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 44)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 44)) + +// string-literal > boolean +type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true" +>PStringLiteral06 : Symbol(PStringLiteral06, Decl(templateLiteralTypes4.ts, 125, 78)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 47)) + +type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false" +>PStringLiteral07 : Symbol(PStringLiteral07, Decl(templateLiteralTypes4.ts, 128, 99)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 129, 48)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 129, 48)) + +// string-literal > (boolean-literal | undefined | null) +type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true" +>PStringLiteral08 : Symbol(PStringLiteral08, Decl(templateLiteralTypes4.ts, 129, 100)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 132, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 132, 47)) + +type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false" +>PStringLiteral09 : Symbol(PStringLiteral09, Decl(templateLiteralTypes4.ts, 132, 86)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 48)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 48)) + +type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined" +>PStringLiteral10 : Symbol(PStringLiteral10, Decl(templateLiteralTypes4.ts, 133, 89)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 52)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 52)) + +type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null" +>PStringLiteral11 : Symbol(PStringLiteral11, Decl(templateLiteralTypes4.ts, 134, 101)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 135, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 135, 47)) + +// #endregion string-literal + +// #region string-literal-enum +// string-literal-enum > number +type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum00 : Symbol(PStringLiteralEnum00, Decl(templateLiteralTypes4.ts, 135, 86)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 140, 48)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 140, 48)) + +// string-literal-enum > enum +type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum01 : Symbol(PStringLiteralEnum01, Decl(templateLiteralTypes4.ts, 140, 100)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 143, 48)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 143, 48)) + +// string-literal-enum > (number-literal | number-literal-enum) +type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum02 : Symbol(PStringLiteralEnum02, Decl(templateLiteralTypes4.ts, 143, 108)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 146, 48)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 146, 48)) + +type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum03 : Symbol(PStringLiteralEnum03, Decl(templateLiteralTypes4.ts, 146, 95)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 147, 48)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 147, 48)) + +// string-literal-enum > bigint +type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum04 : Symbol(PStringLiteralEnum04, Decl(templateLiteralTypes4.ts, 147, 111)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 150, 48)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 150, 48)) + +// string-literal-enum > bigint-literal +type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum05 : Symbol(PStringLiteralEnum05, Decl(templateLiteralTypes4.ts, 150, 100)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 153, 48)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 153, 48)) + +// string-literal-enum > boolean +type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True +>PStringLiteralEnum06 : Symbol(PStringLiteralEnum06, Decl(templateLiteralTypes4.ts, 153, 96)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 156, 51)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 156, 51)) + +type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False +>PStringLiteralEnum07 : Symbol(PStringLiteralEnum07, Decl(templateLiteralTypes4.ts, 156, 104)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 157, 52)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 157, 52)) + +// string-literal-enum > (boolean-literal | undefined | null) +type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True +>PStringLiteralEnum08 : Symbol(PStringLiteralEnum08, Decl(templateLiteralTypes4.ts, 157, 105)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 160, 51)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 160, 51)) + +type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False +>PStringLiteralEnum09 : Symbol(PStringLiteralEnum09, Decl(templateLiteralTypes4.ts, 160, 101)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 161, 52)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 161, 52)) + +type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined +>PStringLiteralEnum10 : Symbol(PStringLiteralEnum10, Decl(templateLiteralTypes4.ts, 161, 103)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 162, 56)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 162, 56)) + +type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null +>PStringLiteralEnum11 : Symbol(PStringLiteralEnum11, Decl(templateLiteralTypes4.ts, 162, 111)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 163, 51)) +>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 163, 51)) + +// #endregion string-literal-enum + +// #region number +// number > enum +type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0 +>PNumber0 : Symbol(PNumber0, Decl(templateLiteralTypes4.ts, 163, 101)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 168, 36)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 168, 36)) + +// number > number-literal-enum +type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0 +>PNumber1 : Symbol(PNumber1, Decl(templateLiteralTypes4.ts, 168, 85)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 171, 36)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 171, 36)) + +// number > bigint +type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0 +>PNumber2 : Symbol(PNumber2, Decl(templateLiteralTypes4.ts, 171, 88)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 174, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 174, 36)) + +// number > bigint-literal +type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0 +>PNumber3 : Symbol(PNumber3, Decl(templateLiteralTypes4.ts, 174, 77)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 177, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 177, 36)) + +// #endregion number + +// #region enum +// enum > number-literal-enum +type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0 +>PEnum0 : Symbol(PEnum0, Decl(templateLiteralTypes4.ts, 177, 73)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 182, 34)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 182, 34)) + +// enum > bigint +type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0 +>PEnum1 : Symbol(PEnum1, Decl(templateLiteralTypes4.ts, 182, 94)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 185, 34)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 185, 34)) + +// enum > bigint-literal +type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0 +>PEnum2 : Symbol(PEnum2, Decl(templateLiteralTypes4.ts, 185, 83)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 188, 34)) +>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 188, 34)) + +// #endregion enum + +// #region number-literal +// number-literal > bigint +type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0 +>PNumberLiteral0 : Symbol(PNumberLiteral0, Decl(templateLiteralTypes4.ts, 188, 79)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 193, 43)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 193, 43)) + +// number-literal > bigint-literal +type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0 +>PNumberLiteral1 : Symbol(PNumberLiteral1, Decl(templateLiteralTypes4.ts, 193, 79)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 196, 43)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 196, 43)) + +// #endregion number-literal + +// #region number-literal-enum +// number-literal-enum > bigint +type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero +>PNumberLiteralEnum0 : Symbol(PNumberLiteralEnum0, Decl(templateLiteralTypes4.ts, 196, 75)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 201, 47)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 201, 47)) + +// number-literal-enum > bigint-literal +type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero +>PNumberLiteralEnum1 : Symbol(PNumberLiteralEnum1, Decl(templateLiteralTypes4.ts, 201, 99)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 204, 47)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 204, 47)) + +// #endregion number-literal-enum + +// non-matchable constituents are excluded +type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0 +>PExclude0 : Symbol(PExclude0, Decl(templateLiteralTypes4.ts, 204, 95)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 208, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 208, 37)) + +type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0 +>PExclude1 : Symbol(PExclude1, Decl(templateLiteralTypes4.ts, 208, 75)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 209, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 209, 37)) + +type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n +>PExclude2 : Symbol(PExclude2, Decl(templateLiteralTypes4.ts, 209, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 210, 37)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 210, 37)) + +type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n +>PExclude3 : Symbol(PExclude3, Decl(templateLiteralTypes4.ts, 210, 73)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 211, 37)) +>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90)) +>One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 211, 37)) + +type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n +>PExclude4 : Symbol(PExclude4, Decl(templateLiteralTypes4.ts, 211, 93)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 212, 60)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 212, 60)) + +// infer to prefix from string +type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1 +>TPrefix0 : Symbol(TPrefix0, Decl(templateLiteralTypes4.ts, 212, 101)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 215, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 215, 38)) + +type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string) +>TPrefix1 : Symbol(TPrefix1, Decl(templateLiteralTypes4.ts, 215, 79)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 216, 42)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 216, 42)) + +type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':') +>TPrefix2 : Symbol(TPrefix2, Decl(templateLiteralTypes4.ts, 216, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 217, 48)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 217, 48)) + +// can use union w/multiple branches to extract each possibility type ExtractPrimitives = ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23)) | T ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23)) | (T extends `${infer U extends number}` ? U : never) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 56, 25)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 56, 25)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 222, 25)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 222, 25)) | (T extends `${infer U extends bigint}` ? U : never) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 57, 25)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 57, 25)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 223, 25)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 223, 25)) | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 54, 23)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 25)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 58, 25)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 224, 25)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 224, 25)) ; -type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n ->T570 : Symbol(T570, Decl(templateLiteralTypes4.ts, 59, 5)) ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) +// .types tests here are worthless until #48578 is merged +type Check = void; +>Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 228, 11)) +>U : Symbol(U, Decl(templateLiteralTypes4.ts, 228, 13)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 228, 11)) + +type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n +>TExtract0 : Symbol(TExtract0, Decl(templateLiteralTypes4.ts, 228, 34)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90)) + +type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 +>TExtract1 : Symbol(TExtract1, Decl(templateLiteralTypes4.ts, 230, 42)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90)) + +type TExtract2 = ExtractPrimitives<"true">; // "true" | true +>TExtract2 : Symbol(TExtract2, Decl(templateLiteralTypes4.ts, 231, 42)) +>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90)) + +type _ = [ +>_ : Symbol(_, Decl(templateLiteralTypes4.ts, 232, 43)) + + Check, +>Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) +>TExtract0 : Symbol(TExtract0, Decl(templateLiteralTypes4.ts, 228, 34)) -type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 ->T571 : Symbol(T571, Decl(templateLiteralTypes4.ts, 61, 37)) ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) + Check, +>Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) +>TExtract1 : Symbol(TExtract1, Decl(templateLiteralTypes4.ts, 230, 42)) -type T572 = ExtractPrimitives<"true">; // "true" | true ->T572 : Symbol(T572, Decl(templateLiteralTypes4.ts, 62, 37)) ->ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 52, 87)) + Check, +>Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) +>TExtract2 : Symbol(TExtract2, Decl(templateLiteralTypes4.ts, 231, 42)) -type NumberFor = S extends `${infer N extends number}` ? N : never; ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 65, 15)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 65, 15)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 65, 53)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 65, 53)) +]; -type T60 = NumberFor<"100">; // 100 ->T60 : Symbol(T60, Decl(templateLiteralTypes4.ts, 65, 85)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) -type T61 = NumberFor; // never ->T61 : Symbol(T61, Decl(templateLiteralTypes4.ts, 66, 28)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) -type T62 = NumberFor; // never ->T62 : Symbol(T62, Decl(templateLiteralTypes4.ts, 67, 26)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) +// example use case (based on old TypedObjects proposal): + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndexFor = S extends `${infer N extends number}` ? N : never; +>IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 238, 2)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 245, 14)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 245, 14)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 245, 52)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 245, 52)) + +type IndicesOf = IndexFor>; // ordinal indices as number literals +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 245, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 246, 15)) +>IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 238, 2)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 246, 15)) -// example use case: interface FieldDefinition { ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) readonly name: string; ->name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 71, 27)) +>name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 248, 27)) readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; ->type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 72, 26)) +>type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 249, 26)) } type FieldType = ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 253, 15)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 253, 15)) T extends "f32" | "f64" ? bigint : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 253, 15)) never; // Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectNamedMembers = { ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 79, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 82, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 256, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 259, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) [P in TDef[number]["name"]]: FieldType["type"]>; ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 83, 5)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 82, 29)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 260, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 259, 29)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 82, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 83, 66)) ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 83, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 259, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 260, 66)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 260, 5)) }; // Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectOrdinalMembers = { ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 84, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 87, 31)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 261, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 264, 31)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) [I in Extract]: FieldType["type"]>; ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 88, 5)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 265, 5)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 87, 31)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 264, 31)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 87, 31)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 88, 5)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 264, 31)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 265, 5)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) }; // Default members interface TypedObjectMembers { ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 89, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 266, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) // get/set a field by name get(key: K): FieldType["type"]>; ->get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 92, 71)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 94, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 94, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 94, 8)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) +>get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 269, 71)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 271, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 271, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 271, 8)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 94, 82)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 94, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 271, 82)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 271, 8)) set(key: K, value: FieldType["type"]>): void; ->set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 94, 112)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 95, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 95, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 95, 8)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 95, 47)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) +>set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 271, 112)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 272, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 272, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 272, 8)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 272, 47)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 95, 88)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 95, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 272, 88)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 272, 8)) // get/set a field by index getIndex>(index: I): FieldType["type"]>; ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 98, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 100, 1)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 98, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 98, 13)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 275, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 245, 84)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 275, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 275, 13)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 98, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 275, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) setIndex>(index: I, value: FieldType["type"]>): void; ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 99, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 100, 1)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 99, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 99, 13)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 99, 49)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 74, 1)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 276, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 245, 84)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 276, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 276, 13)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 276, 49)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 92, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 99, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 276, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) } -// Use constrained `infer` in template literal to get ordinal indices as numbers: -type IndicesOf = NumberFor>; // ordinal indices as number literals ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 100, 1)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 103, 15)) ->NumberFor : Symbol(NumberFor, Decl(templateLiteralTypes4.ts, 63, 38)) ->Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 103, 15)) - type TypedObject = ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 103, 56)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 68, 28)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 277, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) & TypedObjectMembers ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 89, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 266, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) & TypedObjectNamedMembers ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 79, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 256, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) & TypedObjectOrdinalMembers; ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 84, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 105, 17)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 261, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) // NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type type Point = TypedObject<[ ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 108, 38)) ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 103, 56)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 282, 38)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 277, 1)) { name: "x", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 112, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 112, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 286, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 286, 16)) { name: "y", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 113, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 113, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 287, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 287, 16)) ]>; declare const p: Point; ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 108, 38)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 282, 38)) p.getIndex(0); // ok, 0 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) p.getIndex(1); // ok, 1 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) p.getIndex(2); // error, 2 is not a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 95, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) p.setIndex(0, 0); // ok, 0 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) p.setIndex(1, 0); // ok, 1 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) p.setIndex(2, 3); // error, 2 is not a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 116, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 98, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +// function inference declare function f1(s: `**${T}**`): T; ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 123, 17)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 125, 47)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 20)) +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 297, 17)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 300, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) f1("**123**"); // "123" ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 123, 17)) +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 297, 17)) declare function f2(s: `**${T}**`): T; ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 126, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 128, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 20)) +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 301, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 303, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 303, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 303, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 303, 20)) f2("**123**"); // 123 ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 126, 14)) +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 301, 14)) declare function f3(s: `**${T}**`): T; ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 129, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 131, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 131, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 131, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 131, 20)) +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 304, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 306, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 306, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 306, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 306, 20)) f3("**123**"); // 123n ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 129, 14)) +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 304, 14)) declare function f4(s: `**${T}**`): T; ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 132, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 134, 39)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 20)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 307, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 309, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 309, 39)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 309, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 309, 20)) f4("**true**"); // true | "true" ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 132, 14)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 307, 14)) f4("**false**"); // false | "false" ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 132, 14)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 307, 14)) diff --git a/tests/baselines/reference/templateLiteralTypes4.types b/tests/baselines/reference/templateLiteralTypes4.types index 6cfbf5a010919..5ee2c5d8af5e8 100644 --- a/tests/baselines/reference/templateLiteralTypes4.types +++ b/tests/baselines/reference/templateLiteralTypes4.types @@ -1,134 +1,413 @@ === tests/cases/conformance/types/literal/templateLiteralTypes4.ts === -type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 ->T0 : 100 +// infer from number +type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100 +>TNumber0 : 100 -type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 ->T1 : -100 +type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100 +>TNumber1 : -100 -type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 ->T2 : 1.1 +type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 +>TNumber2 : 1.1 -type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) ->T3 : 8e-11 +type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) +>TNumber3 : 8e-11 -type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T4 : number +type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber4 : number -type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T5 : number +type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber5 : number -type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T6 : number +type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber6 : number -type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) ->T7 : number +type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +>TNumber7 : number -type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never ->T8 : never +type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never +>TNumber8 : never -type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n ->T10 : 100n +// infer from bigint +type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n +>TBigInt0 : 100n -type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n ->T11 : -100n +type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n +>TBigInt1 : -100n -type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) ->T12 : bigint +type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>TBigInt2 : bigint -type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) ->T13 : bigint +type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>TBigInt3 : bigint -type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) ->T14 : bigint +type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +>TBigInt4 : bigint -type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never ->T15 : never +type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never +>TBigInt5 : never -type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never ->T16 : never +type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never +>TBigInt6 : never -type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never ->T17 : never +type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never +>TBigInt7 : never -type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true ->T20 : true +// infer from boolean +type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true +>TBoolean0 : true -type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false ->T21 : false +type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false +>TBoolean1 : false -type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never ->T22 : never +type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never +>TBoolean2 : never -type T30 = "null" extends `${infer T extends null}` ? T : never; // null ->T30 : null +// infer from null +type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null +>TNull0 : null >null : null -type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never ->T31 : never +type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never +>TNull1 : never >null : null -type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined ->T40 : undefined +// infer from undefined +type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +>TUndefined0 : undefined + +type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never +>TUndefined1 : never + +// infer from literal enums +const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" } +>StringLiteralEnum : StringLiteralEnum +>Zero : StringLiteralEnum.Zero +>"0" : "0" +>True : StringLiteralEnum.True +>"true" : "true" +>False : StringLiteralEnum.False +>"false" : "false" +>Undefined : StringLiteralEnum.Undefined +>"undefined" : "undefined" +>Null : StringLiteralEnum.Null +>"null" : "null" + +type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero +>TStringLiteralEnum0 : StringLiteralEnum.Zero + +const enum NumberLiteralEnum { Zero, One } +>NumberLiteralEnum : NumberLiteralEnum +>Zero : NumberLiteralEnum.Zero +>One : NumberLiteralEnum.One + +type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero +>TNumberLiteralEnum0 : NumberLiteralEnum.Zero + +// infer from non-literal enums +const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One } +>NonLiteralEnum : NonLiteralEnum +>Zero : NonLiteralEnum +>NumberLiteralEnum.Zero : NumberLiteralEnum.Zero +>NumberLiteralEnum : typeof NumberLiteralEnum +>Zero : NumberLiteralEnum.Zero +>One : NonLiteralEnum +>NumberLiteralEnum.One : NumberLiteralEnum.One +>NumberLiteralEnum : typeof NumberLiteralEnum +>One : NumberLiteralEnum.One + +type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0 +>TNonLiteralEnum0 : 0 + +// infer using priority: +// string > template-literal > (string-literal | string-literal-enum) > +// number > enum > (number-literal | number-literal-enum) > +// bigint > bigint-literal > +// boolean > (boolean-literal | undefined | null) + +// #region string +// string > string-literal-enum +type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0" +>PString00 : "0" + +// string > number +type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0" +>PString01 : "0" + +// string > enum +type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0" +>PString02 : "0" + +// string > (number-literal | number-literal-enum) +type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0" +>PString03 : "0" + +type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0" +>PString04 : "0" + +// string > bigint +type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0" +>PString05 : "0" + +// string > bigint-literal +type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0" +>PString06 : "0" + +// string > boolean +type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" +>PString07 : "true" + +type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" +>PString08 : "false" + +// string > (boolean-literal | undefined | null) +type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true" +>PString09 : "true" +>true : true + +type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false" +>PString10 : "false" +>false : false + +type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" +>PString11 : "undefined" + +type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null" +>PString12 : "null" +>null : null + +// #endregion string + +// #region template-literal +// template-literal > number +type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10" +>PTemplate00 : "10" + +// template-literal > enum +type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10" +>PTemplate01 : "10" + +// template-literal > (number-literal | number-literal-enum) +type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10" +>PTemplate02 : "10" + +type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10" +>PTemplate03 : "10" + +// template-literal > bigint +type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10" +>PTemplate04 : "10" -type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never ->T41 : never +// template-literal > bigint-literal +type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10" +>PTemplate05 : "10" + +// template-literal > boolean +type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true" +>PTemplate06 : "true" + +type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false" +>PTemplate07 : "false" + +// template-literal > (boolean-literal | undefined | null) +type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true" +>PTemplate08 : "true" +>true : true + +type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false" +>PTemplate09 : "false" +>false : false + +type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined" +>PTemplate10 : "undefined" + +type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null" +>PTemplate11 : "null" +>null : null -type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" ->T500 : "100" +// #endregion template-literal -type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 ->T501 : 100 +// #region string-literal +// string-literal > number +type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0" +>PStringLiteral00 : "0" -type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n ->T502 : 100n +// string-literal > enum +type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0" +>PStringLiteral01 : "0" -type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" ->T503 : "100" +// string-literal > (number-literal | number-literal-enum) +type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0" +>PStringLiteral02 : "0" -type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 ->T504 : 100 +type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0" +>PStringLiteral03 : "0" -type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" ->T510 : "1.1" +// string-literal > bigint +type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0" +>PStringLiteral04 : "0" -type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 ->T511 : 1.1 +// string-literal > bigint-literal +type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0" +>PStringLiteral05 : "0" -type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never ->T512 : never +// string-literal > boolean +type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true" +>PStringLiteral06 : "true" -type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" ->T520 : "true" +type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false" +>PStringLiteral07 : "false" -type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true ->T521 : true +// string-literal > (boolean-literal | undefined | null) +type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true" +>PStringLiteral08 : "true" +>true : true -type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" ->T530 : "false" +type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false" +>PStringLiteral09 : "false" +>false : false -type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false ->T531 : false +type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined" +>PStringLiteral10 : "undefined" -type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" ->T540 : "null" +type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null" +>PStringLiteral11 : "null" >null : null -type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null ->T541 : "null" +// #endregion string-literal + +// #region string-literal-enum +// string-literal-enum > number +type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum00 : StringLiteralEnum.Zero + +// string-literal-enum > enum +type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum01 : StringLiteralEnum.Zero + +// string-literal-enum > (number-literal | number-literal-enum) +type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum02 : StringLiteralEnum.Zero + +type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum03 : StringLiteralEnum.Zero + +// string-literal-enum > bigint +type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum04 : StringLiteralEnum.Zero + +// string-literal-enum > bigint-literal +type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero +>PStringLiteralEnum05 : StringLiteralEnum.Zero + +// string-literal-enum > boolean +type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True +>PStringLiteralEnum06 : StringLiteralEnum.True + +type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False +>PStringLiteralEnum07 : StringLiteralEnum.False + +// string-literal-enum > (boolean-literal | undefined | null) +type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True +>PStringLiteralEnum08 : StringLiteralEnum.True +>true : true + +type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False +>PStringLiteralEnum09 : StringLiteralEnum.False +>false : false + +type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined +>PStringLiteralEnum10 : StringLiteralEnum.Undefined + +type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null +>PStringLiteralEnum11 : StringLiteralEnum.Null >null : null -type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" ->T550 : "undefined" +// #endregion string-literal-enum + +// #region number +// number > enum +type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0 +>PNumber0 : 0 + +// number > number-literal-enum +type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0 +>PNumber1 : 0 -type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined ->T551 : undefined +// number > bigint +type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0 +>PNumber2 : 0 -type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n ->T560 : 100000000000000000000000n +// number > bigint-literal +type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0 +>PNumber3 : 0 -type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number ->T561 : number +// #endregion number +// #region enum +// enum > number-literal-enum +type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0 +>PEnum0 : 0 + +// enum > bigint +type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0 +>PEnum1 : 0 + +// enum > bigint-literal +type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0 +>PEnum2 : 0 + +// #endregion enum + +// #region number-literal +// number-literal > bigint +type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0 +>PNumberLiteral0 : 0 + +// number-literal > bigint-literal +type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0 +>PNumberLiteral1 : 0 + +// #endregion number-literal + +// #region number-literal-enum +// number-literal-enum > bigint +type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero +>PNumberLiteralEnum0 : NumberLiteralEnum.Zero + +// number-literal-enum > bigint-literal +type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero +>PNumberLiteralEnum1 : NumberLiteralEnum.Zero + +// #endregion number-literal-enum + +// non-matchable constituents are excluded +type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0 +>PExclude0 : 0 + +type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0 +>PExclude1 : 0 + +type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n +>PExclude2 : 0n + +type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n +>PExclude3 : 0n +>NumberLiteralEnum : any + +type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n +>PExclude4 : 100000000000000000000000n + +// infer to prefix from string +type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1 +>TPrefix0 : 1 + +type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string) +>TPrefix1 : boolean + +type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':') +>TPrefix2 : 100 + +// can use union w/multiple branches to extract each possibility type ExtractPrimitives = >ExtractPrimitives : ExtractPrimitives @@ -140,28 +419,40 @@ type ExtractPrimitives = ; -type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n ->T570 : T570 +// .types tests here are worthless until #48578 is merged +type Check = void; +>Check : void + +type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n +>TExtract0 : TExtract0 + +type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 +>TExtract1 : TExtract1 + +type TExtract2 = ExtractPrimitives<"true">; // "true" | true +>TExtract2 : TExtract2 -type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 ->T571 : T571 +type _ = [ +>_ : _ -type T572 = ExtractPrimitives<"true">; // "true" | true ->T572 : T572 + Check, + Check, + Check, +>true : true -type NumberFor = S extends `${infer N extends number}` ? N : never; ->NumberFor : NumberFor +]; -type T60 = NumberFor<"100">; // 100 ->T60 : 100 -type T61 = NumberFor; // never ->T61 : never -type T62 = NumberFor; // never ->T62 : never +// example use case (based on old TypedObjects proposal): + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndexFor = S extends `${infer N extends number}` ? N : never; +>IndexFor : IndexFor + +type IndicesOf = IndexFor>; // ordinal indices as number literals +>IndicesOf : IndicesOf -// example use case: interface FieldDefinition { readonly name: string; >name : string @@ -209,19 +500,15 @@ interface TypedObjectMembers { // get/set a field by index getIndex>(index: I): FieldType["type"]>; ->getIndex : >>(index: I) => FieldType["type"]> +>getIndex : >>(index: I) => FieldType["type"]> >index : I setIndex>(index: I, value: FieldType["type"]>): void; ->setIndex : >>(index: I, value: FieldType["type"]>) => void +>setIndex : >>(index: I, value: FieldType["type"]>) => void >index : I >value : FieldType["type"]> } -// Use constrained `infer` in template literal to get ordinal indices as numbers: -type IndicesOf = NumberFor>; // ordinal indices as number literals ->IndicesOf : IndicesOf - type TypedObject = >TypedObject : TypedObject @@ -291,6 +578,7 @@ p.setIndex(2, 3); // error, 2 is not a valid index >2 : 2 >3 : 3 +// function inference declare function f1(s: `**${T}**`): T; >f1 : (s: `**${T}**`) => T >s : `**${T}**` diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts index e3228613dc8d8..36d240493dcc0 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts @@ -2,60 +2,226 @@ // @target: esnext // @declaration: true -type T0 = "100" extends `${infer N extends number}` ? N : never; // 100 -type T1 = "-100" extends `${infer N extends number}` ? N : never; // -100 -type T2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 -type T3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) -type T4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) -type T8 = "abcd" extends `${infer N extends number}` ? N : never; // never - -type T10 = "100" extends `${infer N extends bigint}` ? N : never; // 100n -type T11 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n -type T12 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) -type T13 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) -type T14 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) -type T15 = "1.1" extends `${infer N extends bigint}` ? N : never; // never -type T16 = "10e2" extends `${infer N extends bigint}` ? N : never; // never -type T17 = "abcd" extends `${infer N extends bigint}` ? N : never; // never - -type T20 = "true" extends `${infer T extends boolean}` ? T : never; // true -type T21 = "false" extends `${infer T extends boolean}` ? T : never; // false -type T22 = "abcd" extends `${infer T extends boolean}` ? T : never; // never - -type T30 = "null" extends `${infer T extends null}` ? T : never; // null -type T31 = "abcd" extends `${infer T extends null}` ? T : never; // never - -type T40 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined -type T41 = "abcd" extends `${infer T extends undefined}` ? T : never; // never - -type T500 = "100" extends `${infer T extends string | number | bigint}` ? T : never; // "100" -type T501 = "100" extends `${infer T extends number | bigint}` ? T : never; // 100 -type T502 = "100" extends `${infer T extends bigint}` ? T : never; // 100n -type T503 = "100" extends `${infer T extends "100" | number}` ? T : never; // "100" -type T504 = "100" extends `${infer T extends "101" | number}` ? T : never; // 100 - -type T510 = "1.1" extends `${infer T extends string | number | bigint}` ? T : never; // "1.1" -type T511 = "1.1" extends `${infer T extends number | bigint}` ? T : never; // 1.1 -type T512 = "1.1" extends `${infer T extends bigint}` ? T : never; // never - -type T520 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" -type T521 = "true" extends `${infer T extends boolean}` ? T : never; // true - -type T530 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" -type T531 = "false" extends `${infer T extends boolean}` ? T : never; // false - -type T540 = "null" extends `${infer T extends string | null}` ? T : never; // "null" -type T541 = "null" extends `${infer T extends string | null}` ? T : never; // null - -type T550 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" -type T551 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined - -type T560 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n -type T561 = "100000000000000000000000" extends `${infer T extends number}` ? T : never; // number +// infer from number +type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100 +type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100 +type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1 +type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008) +type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable) +type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never +// infer from bigint +type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n +type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n +type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable) +type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never +type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never +type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never + +// infer from boolean +type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true +type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false +type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never + +// infer from null +type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null +type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never + +// infer from undefined +type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined +type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never + +// infer from literal enums +const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" } +type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + +const enum NumberLiteralEnum { Zero, One } +type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero + +// infer from non-literal enums +const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One } +type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0 + +// infer using priority: +// string > template-literal > (string-literal | string-literal-enum) > +// number > enum > (number-literal | number-literal-enum) > +// bigint > bigint-literal > +// boolean > (boolean-literal | undefined | null) + +// #region string +// string > string-literal-enum +type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0" + +// string > number +type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0" + +// string > enum +type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0" + +// string > (number-literal | number-literal-enum) +type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0" +type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0" + +// string > bigint +type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0" + +// string > bigint-literal +type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0" + +// string > boolean +type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true" +type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false" + +// string > (boolean-literal | undefined | null) +type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true" +type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false" +type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined" +type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null" +// #endregion string + +// #region template-literal +// template-literal > number +type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10" + +// template-literal > enum +type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10" + +// template-literal > (number-literal | number-literal-enum) +type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10" +type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10" + +// template-literal > bigint +type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10" + +// template-literal > bigint-literal +type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10" + +// template-literal > boolean +type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true" +type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false" + +// template-literal > (boolean-literal | undefined | null) +type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true" +type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false" +type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined" +type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null" +// #endregion template-literal + +// #region string-literal +// string-literal > number +type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0" + +// string-literal > enum +type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0" + +// string-literal > (number-literal | number-literal-enum) +type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0" +type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0" + +// string-literal > bigint +type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0" + +// string-literal > bigint-literal +type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0" + +// string-literal > boolean +type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true" +type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false" + +// string-literal > (boolean-literal | undefined | null) +type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true" +type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false" +type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined" +type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null" +// #endregion string-literal + +// #region string-literal-enum +// string-literal-enum > number +type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > enum +type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > (number-literal | number-literal-enum) +type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero +type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > bigint +type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > bigint-literal +type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero + +// string-literal-enum > boolean +type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True +type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False + +// string-literal-enum > (boolean-literal | undefined | null) +type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True +type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False +type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined +type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null +// #endregion string-literal-enum + +// #region number +// number > enum +type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0 + +// number > number-literal-enum +type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0 + +// number > bigint +type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0 + +// number > bigint-literal +type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0 +// #endregion number + +// #region enum +// enum > number-literal-enum +type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0 + +// enum > bigint +type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0 + +// enum > bigint-literal +type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0 +// #endregion enum + +// #region number-literal +// number-literal > bigint +type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0 + +// number-literal > bigint-literal +type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0 +// #endregion number-literal + +// #region number-literal-enum +// number-literal-enum > bigint +type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero + +// number-literal-enum > bigint-literal +type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero +// #endregion number-literal-enum + +// non-matchable constituents are excluded +type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0 +type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0 +type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n +type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n +type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n + +// infer to prefix from string +type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1 +type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string) +type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':') + +// can use union w/multiple branches to extract each possibility type ExtractPrimitives = | T | (T extends `${infer U extends number}` ? U : never) @@ -63,16 +229,27 @@ type ExtractPrimitives = | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; -type T570 = ExtractPrimitives<"100">; // "100" | 100 | 100n -type T571 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 -type T572 = ExtractPrimitives<"true">; // "true" | true +// .types tests here are worthless until #48578 is merged +type Check = void; + +type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n +type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 +type TExtract2 = ExtractPrimitives<"true">; // "true" | true -type NumberFor = S extends `${infer N extends number}` ? N : never; -type T60 = NumberFor<"100">; // 100 -type T61 = NumberFor; // never -type T62 = NumberFor; // never +type _ = [ + Check, + Check, + Check, +]; + + + +// example use case (based on old TypedObjects proposal): + +// Use constrained `infer` in template literal to get ordinal indices as numbers: +type IndexFor = S extends `${infer N extends number}` ? N : never; +type IndicesOf = IndexFor>; // ordinal indices as number literals -// example use case: interface FieldDefinition { readonly name: string; readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; @@ -104,9 +281,6 @@ interface TypedObjectMembers { setIndex>(index: I, value: FieldType["type"]>): void; } -// Use constrained `infer` in template literal to get ordinal indices as numbers: -type IndicesOf = NumberFor>; // ordinal indices as number literals - type TypedObject = & TypedObjectMembers & TypedObjectNamedMembers @@ -127,6 +301,7 @@ p.setIndex(0, 0); // ok, 0 is a valid index p.setIndex(1, 0); // ok, 1 is a valid index p.setIndex(2, 3); // error, 2 is not a valid index +// function inference declare function f1(s: `**${T}**`): T; f1("**123**"); // "123" From 00c4b2678b45fd639f96028d842f422161f659d6 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 Apr 2022 11:12:36 -0700 Subject: [PATCH 08/10] Update .types tests --- .../templateLiteralTypes4.errors.txt | 13 +- .../reference/templateLiteralTypes4.js | 15 - .../reference/templateLiteralTypes4.symbols | 306 ++++++++---------- .../reference/templateLiteralTypes4.types | 22 +- .../types/literal/templateLiteralTypes4.ts | 9 - 5 files changed, 147 insertions(+), 218 deletions(-) diff --git a/tests/baselines/reference/templateLiteralTypes4.errors.txt b/tests/baselines/reference/templateLiteralTypes4.errors.txt index afb05fc4b661b..57a17a37b0e84 100644 --- a/tests/baselines/reference/templateLiteralTypes4.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes4.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(294,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. -tests/cases/conformance/types/literal/templateLiteralTypes4.ts(298,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(285,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. +tests/cases/conformance/types/literal/templateLiteralTypes4.ts(289,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'. ==== tests/cases/conformance/types/literal/templateLiteralTypes4.ts (2 errors) ==== @@ -230,19 +230,10 @@ tests/cases/conformance/types/literal/templateLiteralTypes4.ts(298,12): error TS | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; - // .types tests here are worthless until #48578 is merged - type Check = void; - type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 type TExtract2 = ExtractPrimitives<"true">; // "true" | true - type _ = [ - Check, - Check, - Check, - ]; - // example use case (based on old TypedObjects proposal): diff --git a/tests/baselines/reference/templateLiteralTypes4.js b/tests/baselines/reference/templateLiteralTypes4.js index 2ab3e60f30c1b..00ef80ae37977 100644 --- a/tests/baselines/reference/templateLiteralTypes4.js +++ b/tests/baselines/reference/templateLiteralTypes4.js @@ -226,19 +226,10 @@ type ExtractPrimitives = | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; -// .types tests here are worthless until #48578 is merged -type Check = void; - type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 type TExtract2 = ExtractPrimitives<"true">; // "true" | true -type _ = [ - Check, - Check, - Check, -]; - // example use case (based on old TypedObjects proposal): @@ -440,15 +431,9 @@ declare type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : declare type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; declare type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; declare type ExtractPrimitives = T | (T extends `${infer U extends number}` ? U : never) | (T extends `${infer U extends bigint}` ? U : never) | (T extends `${infer U extends boolean | null | undefined}` ? U : never); -declare type Check = void; declare type TExtract0 = ExtractPrimitives<"100">; declare type TExtract1 = ExtractPrimitives<"1.1">; declare type TExtract2 = ExtractPrimitives<"true">; -declare type _ = [ - Check, - Check, - Check -]; declare type IndexFor = S extends `${infer N extends number}` ? N : never; declare type IndicesOf = IndexFor>; interface FieldDefinition { diff --git a/tests/baselines/reference/templateLiteralTypes4.symbols b/tests/baselines/reference/templateLiteralTypes4.symbols index d4376a7aa1aac..924812de013ac 100644 --- a/tests/baselines/reference/templateLiteralTypes4.symbols +++ b/tests/baselines/reference/templateLiteralTypes4.symbols @@ -636,287 +636,263 @@ type ExtractPrimitives = ; -// .types tests here are worthless until #48578 is merged -type Check = void; ->Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 228, 11)) ->U : Symbol(U, Decl(templateLiteralTypes4.ts, 228, 13)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 228, 11)) - type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n ->TExtract0 : Symbol(TExtract0, Decl(templateLiteralTypes4.ts, 228, 34)) +>TExtract0 : Symbol(TExtract0, Decl(templateLiteralTypes4.ts, 225, 5)) >ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90)) type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 ->TExtract1 : Symbol(TExtract1, Decl(templateLiteralTypes4.ts, 230, 42)) +>TExtract1 : Symbol(TExtract1, Decl(templateLiteralTypes4.ts, 227, 42)) >ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90)) type TExtract2 = ExtractPrimitives<"true">; // "true" | true ->TExtract2 : Symbol(TExtract2, Decl(templateLiteralTypes4.ts, 231, 42)) +>TExtract2 : Symbol(TExtract2, Decl(templateLiteralTypes4.ts, 228, 42)) >ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90)) -type _ = [ ->_ : Symbol(_, Decl(templateLiteralTypes4.ts, 232, 43)) - - Check, ->Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) ->TExtract0 : Symbol(TExtract0, Decl(templateLiteralTypes4.ts, 228, 34)) - - Check, ->Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) ->TExtract1 : Symbol(TExtract1, Decl(templateLiteralTypes4.ts, 230, 42)) - - Check, ->Check : Symbol(Check, Decl(templateLiteralTypes4.ts, 225, 5)) ->TExtract2 : Symbol(TExtract2, Decl(templateLiteralTypes4.ts, 231, 42)) - -]; - // example use case (based on old TypedObjects proposal): // Use constrained `infer` in template literal to get ordinal indices as numbers: type IndexFor = S extends `${infer N extends number}` ? N : never; ->IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 238, 2)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 245, 14)) ->S : Symbol(S, Decl(templateLiteralTypes4.ts, 245, 14)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 245, 52)) ->N : Symbol(N, Decl(templateLiteralTypes4.ts, 245, 52)) +>IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 229, 43)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 236, 14)) +>S : Symbol(S, Decl(templateLiteralTypes4.ts, 236, 14)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 236, 52)) +>N : Symbol(N, Decl(templateLiteralTypes4.ts, 236, 52)) type IndicesOf = IndexFor>; // ordinal indices as number literals ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 245, 84)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 246, 15)) ->IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 238, 2)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 236, 84)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 237, 15)) +>IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 229, 43)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 246, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 237, 15)) interface FieldDefinition { ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) readonly name: string; ->name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 248, 27)) +>name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 239, 27)) readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"; ->type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 249, 26)) +>type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 240, 26)) } type FieldType = ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 253, 15)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 244, 15)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 253, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 244, 15)) T extends "f32" | "f64" ? bigint : ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 253, 15)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 244, 15)) never; // Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectNamedMembers = { ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 256, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 259, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 247, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 250, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) [P in TDef[number]["name"]]: FieldType["type"]>; ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 260, 5)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 259, 29)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 251, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 250, 29)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 259, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 260, 66)) ->P : Symbol(P, Decl(templateLiteralTypes4.ts, 260, 5)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 250, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 251, 66)) +>P : Symbol(P, Decl(templateLiteralTypes4.ts, 251, 5)) }; // Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]` type TypedObjectOrdinalMembers = { ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 261, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 264, 31)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 252, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 255, 31)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) [I in Extract]: FieldType["type"]>; ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 265, 5)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 256, 5)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 264, 31)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 255, 31)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 264, 31)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 265, 5)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 255, 31)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 256, 5)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) }; // Default members interface TypedObjectMembers { ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 266, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 257, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) // get/set a field by name get(key: K): FieldType["type"]>; ->get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 269, 71)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 271, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 271, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 271, 8)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) +>get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 260, 71)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 262, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 262, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 262, 8)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 271, 82)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 271, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 262, 82)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 262, 8)) set(key: K, value: FieldType["type"]>): void; ->set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 271, 112)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 272, 8)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->key : Symbol(key, Decl(templateLiteralTypes4.ts, 272, 40)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 272, 8)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 272, 47)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) +>set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 262, 112)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 263, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>key : Symbol(key, Decl(templateLiteralTypes4.ts, 263, 40)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 263, 8)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 263, 47)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 272, 88)) ->K : Symbol(K, Decl(templateLiteralTypes4.ts, 272, 8)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 263, 88)) +>K : Symbol(K, Decl(templateLiteralTypes4.ts, 263, 8)) // get/set a field by index getIndex>(index: I): FieldType["type"]>; ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 275, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 245, 84)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 275, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 275, 13)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 266, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 236, 84)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 266, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 266, 13)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 275, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 266, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) setIndex>(index: I, value: FieldType["type"]>): void; ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 276, 13)) ->IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 245, 84)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->index : Symbol(index, Decl(templateLiteralTypes4.ts, 276, 40)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 276, 13)) ->value : Symbol(value, Decl(templateLiteralTypes4.ts, 276, 49)) ->FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 251, 1)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 267, 13)) +>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 236, 84)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>index : Symbol(index, Decl(templateLiteralTypes4.ts, 267, 40)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 267, 13)) +>value : Symbol(value, Decl(templateLiteralTypes4.ts, 267, 49)) +>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 269, 29)) ->I : Symbol(I, Decl(templateLiteralTypes4.ts, 276, 13)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29)) +>I : Symbol(I, Decl(templateLiteralTypes4.ts, 267, 13)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) } type TypedObject = ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 277, 1)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) ->FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 246, 55)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 268, 1)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17)) +>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55)) & TypedObjectMembers ->TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 266, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) +>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 257, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17)) & TypedObjectNamedMembers ->TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 256, 10)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) +>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 247, 10)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17)) & TypedObjectOrdinalMembers; ->TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 261, 2)) ->TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 279, 17)) +>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 252, 2)) +>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17)) // NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type type Point = TypedObject<[ ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 282, 38)) ->TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 277, 1)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 273, 38)) +>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 268, 1)) { name: "x", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 286, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 286, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 277, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 277, 16)) { name: "y", type: "f64" }, ->name : Symbol(name, Decl(templateLiteralTypes4.ts, 287, 5)) ->type : Symbol(type, Decl(templateLiteralTypes4.ts, 287, 16)) +>name : Symbol(name, Decl(templateLiteralTypes4.ts, 278, 5)) +>type : Symbol(type, Decl(templateLiteralTypes4.ts, 278, 16)) ]>; declare const p: Point; ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) ->Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 282, 38)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13)) +>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 273, 38)) p.getIndex(0); // ok, 0 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125)) p.getIndex(1); // ok, 1 is a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125)) p.getIndex(2); // error, 2 is not a valid index ->p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) ->getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 272, 125)) +>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13)) +>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125)) p.setIndex(0, 0); // ok, 0 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104)) p.setIndex(1, 0); // ok, 1 is a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104)) p.setIndex(2, 3); // error, 2 is not a valid index ->p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) ->p : Symbol(p, Decl(templateLiteralTypes4.ts, 290, 13)) ->setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 275, 104)) +>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104)) +>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13)) +>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104)) // function inference declare function f1(s: `**${T}**`): T; ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 297, 17)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 300, 47)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 288, 17)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 291, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 291, 47)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 291, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 291, 20)) f1("**123**"); // "123" ->f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 297, 17)) +>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 288, 17)) declare function f2(s: `**${T}**`): T; ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 301, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 303, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 303, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 303, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 303, 20)) +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 292, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 294, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 294, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 294, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 294, 20)) f2("**123**"); // 123 ->f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 301, 14)) +>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 292, 14)) declare function f3(s: `**${T}**`): T; ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 304, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 306, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 306, 38)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 306, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 306, 20)) +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 295, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 297, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 297, 38)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 297, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 297, 20)) f3("**123**"); // 123n ->f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 304, 14)) +>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 295, 14)) declare function f4(s: `**${T}**`): T; ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 307, 14)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 309, 20)) ->s : Symbol(s, Decl(templateLiteralTypes4.ts, 309, 39)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 309, 20)) ->T : Symbol(T, Decl(templateLiteralTypes4.ts, 309, 20)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 298, 14)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) +>s : Symbol(s, Decl(templateLiteralTypes4.ts, 300, 39)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) +>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20)) f4("**true**"); // true | "true" ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 307, 14)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 298, 14)) f4("**false**"); // false | "false" ->f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 307, 14)) +>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 298, 14)) diff --git a/tests/baselines/reference/templateLiteralTypes4.types b/tests/baselines/reference/templateLiteralTypes4.types index 5ee2c5d8af5e8..d9a1064bec002 100644 --- a/tests/baselines/reference/templateLiteralTypes4.types +++ b/tests/baselines/reference/templateLiteralTypes4.types @@ -419,28 +419,14 @@ type ExtractPrimitives = ; -// .types tests here are worthless until #48578 is merged -type Check = void; ->Check : void - type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n ->TExtract0 : TExtract0 +>TExtract0 : "100" | 100 | 100n type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 ->TExtract1 : TExtract1 +>TExtract1 : "1.1" | 1.1 type TExtract2 = ExtractPrimitives<"true">; // "true" | true ->TExtract2 : TExtract2 - -type _ = [ ->_ : _ - - Check, - Check, - Check, ->true : true - -]; +>TExtract2 : true | "true" @@ -518,7 +504,7 @@ type TypedObject = // NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type type Point = TypedObject<[ ->Point : Point +>Point : TypedObjectMembers<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }]> & TypedObjectNamedMembers<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }]> & TypedObjectOrdinalMembers<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }]> { name: "x", type: "f64" }, >name : "x" diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts index 36d240493dcc0..9976c2297d87e 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes4.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes4.ts @@ -229,19 +229,10 @@ type ExtractPrimitives = | (T extends `${infer U extends boolean | null | undefined}` ? U : never) ; -// .types tests here are worthless until #48578 is merged -type Check = void; - type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1 type TExtract2 = ExtractPrimitives<"true">; // "true" | true -type _ = [ - Check, - Check, - Check, -]; - // example use case (based on old TypedObjects proposal): From e502377dc58421a30e2f5a718f6736ff7bd4d7ff Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 May 2022 16:04:22 -0700 Subject: [PATCH 09/10] Remove TemplateTypePlaceholderPriority --- src/compiler/checker.ts | 60 +++++++++++------------------------------ 1 file changed, 16 insertions(+), 44 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a43ce7c036c86..be537cb202742 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -263,20 +263,6 @@ namespace ts { VoidIsNonOptional = 1 << 1, } - const enum TemplateTypePlaceholderPriority { - Never, // lowest - KeywordLiterals, // true | false | null | undefined - Boolean, - BigIntLiterals, - BigInt, - NumberLiterals, - Enums, - Number, - StringLiterals, - TemplateLiterals, - String, // highest - } - const enum IntrinsicTypeKind { Uppercase, Lowercase, @@ -22743,23 +22729,6 @@ namespace ts { } } - function getTemplateTypePlaceholderPriority(type: Type) { - return type.flags & TypeFlags.String ? TemplateTypePlaceholderPriority.String : - type.flags & TypeFlags.TemplateLiteral ? TemplateTypePlaceholderPriority.TemplateLiterals : - type.flags & TypeFlags.StringMapping ? TemplateTypePlaceholderPriority.StringLiterals : - type.flags & TypeFlags.StringLiteral ? TemplateTypePlaceholderPriority.StringLiterals : - type.flags & TypeFlags.Number ? TemplateTypePlaceholderPriority.Number : - type.flags & TypeFlags.Enum ? TemplateTypePlaceholderPriority.Enums : - type.flags & TypeFlags.NumberLiteral ? TemplateTypePlaceholderPriority.NumberLiterals : - type.flags & TypeFlags.BigInt ? TemplateTypePlaceholderPriority.BigInt : - type.flags & TypeFlags.BigIntLiteral ? TemplateTypePlaceholderPriority.BigIntLiterals : - type.flags & TypeFlags.Boolean ? TemplateTypePlaceholderPriority.Boolean : - type.flags & TypeFlags.BooleanLiteral ? TemplateTypePlaceholderPriority.KeywordLiterals : - type.flags & TypeFlags.Undefined ? TemplateTypePlaceholderPriority.KeywordLiterals : - type.flags & TypeFlags.Null ? TemplateTypePlaceholderPriority.KeywordLiterals : - TemplateTypePlaceholderPriority.Never; - } - function inferToTemplateLiteralType(source: Type, target: TemplateLiteralType) { const matches = inferTypesFromTemplateLiteralType(source, target); const types = target.types; @@ -22797,19 +22766,22 @@ namespace ts { } // for each type in the constraint, find the highest priority matching type - const matchingType = reduceType(constraint, (matchingType, t) => - !(t.flags & allTypeFlags) || getTemplateTypePlaceholderPriority(t) <= getTemplateTypePlaceholderPriority(matchingType) ? matchingType : - t.flags & TypeFlags.String ? source : - t.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, t as TemplateLiteralType) ? source : - t.flags & TypeFlags.StringMapping && str === applyStringMapping(t.symbol, str) ? source : - t.flags & (TypeFlags.Number | TypeFlags.Enum) ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number and TypeFlags.Enum would have been excluded above. - t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above. - t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType : - t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t : - t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t : - t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t : - t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t : - matchingType, + const matchingType = reduceType(constraint, (left, right) => + !(right.flags & allTypeFlags) ? left : + left.flags & TypeFlags.String ? left : right.flags & TypeFlags.String ? source : + left.flags & TypeFlags.TemplateLiteral ? left : right.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, right as TemplateLiteralType) ? source : + left.flags & TypeFlags.StringMapping ? left : right.flags & TypeFlags.StringMapping && str === applyStringMapping(right.symbol, str) ? source : + left.flags & TypeFlags.StringLiteral ? left : right.flags & TypeFlags.StringLiteral && (right as StringLiteralType).value === str ? right : + left.flags & TypeFlags.Number ? left : right.flags & TypeFlags.Number ? getNumberLiteralType(+str) : + left.flags & TypeFlags.Enum ? left : right.flags & TypeFlags.Enum ? getNumberLiteralType(+str) : + left.flags & TypeFlags.NumberLiteral ? left : right.flags & TypeFlags.NumberLiteral && (right as NumberLiteralType).value === +str ? right : + left.flags & TypeFlags.BigInt ? left : right.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : + left.flags & TypeFlags.BigIntLiteral ? left : right.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((right as BigIntLiteralType).value) === str ? right : + left.flags & TypeFlags.Boolean ? left : right.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType : + left.flags & TypeFlags.BooleanLiteral ? left : right.flags & TypeFlags.BooleanLiteral && (right as IntrinsicType).intrinsicName === str ? right : + left.flags & TypeFlags.Undefined ? left : right.flags & TypeFlags.Undefined && (right as IntrinsicType).intrinsicName === str ? right : + left.flags & TypeFlags.Null ? left : right.flags & TypeFlags.Null && (right as IntrinsicType).intrinsicName === str ? right : + left, neverType as Type); if (!(matchingType.flags & TypeFlags.Never)) { From 9ccca98e9881424a258e18f4e33c602fccbc420e Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 May 2022 16:21:22 -0700 Subject: [PATCH 10/10] Remove reduceType --- src/compiler/checker.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index be537cb202742..554c436ae4e80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22749,7 +22749,8 @@ namespace ts { const inferenceContext = getInferenceInfoForType(target); const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined; if (constraint && !isTypeAny(constraint)) { - let allTypeFlags = reduceType(constraint, (flags, t) => flags | t.flags, 0 as TypeFlags); + const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint]; + let allTypeFlags: TypeFlags = reduceLeft(constraintTypes, (flags, t) => flags | t.flags, 0 as TypeFlags); // If the constraint contains `string`, we don't need to look for a more preferred type if (!(allTypeFlags & TypeFlags.String)) { @@ -22766,7 +22767,7 @@ namespace ts { } // for each type in the constraint, find the highest priority matching type - const matchingType = reduceType(constraint, (left, right) => + const matchingType = reduceLeft(constraintTypes, (left, right) => !(right.flags & allTypeFlags) ? left : left.flags & TypeFlags.String ? left : right.flags & TypeFlags.String ? source : left.flags & TypeFlags.TemplateLiteral ? left : right.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, right as TemplateLiteralType) ? source : @@ -22777,7 +22778,7 @@ namespace ts { left.flags & TypeFlags.NumberLiteral ? left : right.flags & TypeFlags.NumberLiteral && (right as NumberLiteralType).value === +str ? right : left.flags & TypeFlags.BigInt ? left : right.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : left.flags & TypeFlags.BigIntLiteral ? left : right.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((right as BigIntLiteralType).value) === str ? right : - left.flags & TypeFlags.Boolean ? left : right.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType : + left.flags & TypeFlags.Boolean ? left : right.flags & TypeFlags.Boolean ? str === "true" ? trueType : str === "false" ? falseType : booleanType : left.flags & TypeFlags.BooleanLiteral ? left : right.flags & TypeFlags.BooleanLiteral && (right as IntrinsicType).intrinsicName === str ? right : left.flags & TypeFlags.Undefined ? left : right.flags & TypeFlags.Undefined && (right as IntrinsicType).intrinsicName === str ? right : left.flags & TypeFlags.Null ? left : right.flags & TypeFlags.Null && (right as IntrinsicType).intrinsicName === str ? right : @@ -23800,12 +23801,6 @@ namespace ts { return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type); } - function reduceType(type: Type, f: (memo: T, t: Type) => T | undefined, initial: T): T; - function reduceType(type: Type, f: (memo: T | undefined, t: Type) => T | undefined): T | undefined; - function reduceType(type: Type, f: (memo: T | undefined, t: Type) => T | undefined, initial?: T | undefined): T | undefined { - return type.flags & TypeFlags.Union ? reduceLeft((type as UnionType).types, f, initial) : f(initial, type); - } - function someType(type: Type, f: (t: Type) => boolean): boolean { return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type); }