From b95ad9799b5320598c4789905a9f55b11207893e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 29 Nov 2023 07:48:15 -0800 Subject: [PATCH 1/2] Consistently check assignability to template literal placeholders --- src/compiler/checker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 87b68e0bf209c..604c283545234 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25017,12 +25017,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean { - if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) { - return true; - } if (target.flags & TypeFlags.Intersection) { return every((target as IntersectionType).types, t => t === emptyTypeLiteralType || isValidTypeForTemplateLiteralPlaceholder(source, t)); } + if (target.flags & TypeFlags.String || isTypeAssignableTo(source, target)) { + return true; + } if (source.flags & TypeFlags.StringLiteral) { const value = (source as StringLiteralType).value; return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) || @@ -25035,7 +25035,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const texts = (source as TemplateLiteralType).texts; return texts.length === 2 && texts[0] === "" && texts[1] === "" && isTypeAssignableTo((source as TemplateLiteralType).types[0], target); } - return isTypeAssignableTo(source, target); + return false; } function inferTypesFromTemplateLiteralType(source: Type, target: TemplateLiteralType): Type[] | undefined { From 0e4c652e20ad64c29a597b218341505564ad4fce Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 29 Nov 2023 07:48:38 -0800 Subject: [PATCH 2/2] Add regression test --- .../templateLiteralTypes3.errors.txt | 8 ++++++++ .../reference/templateLiteralTypes3.js | 17 ++++++++++++++++ .../reference/templateLiteralTypes3.symbols | 19 ++++++++++++++++++ .../reference/templateLiteralTypes3.types | 20 +++++++++++++++++++ .../types/literal/templateLiteralTypes3.ts | 8 ++++++++ 5 files changed, 72 insertions(+) diff --git a/tests/baselines/reference/templateLiteralTypes3.errors.txt b/tests/baselines/reference/templateLiteralTypes3.errors.txt index ffb22d7ceac3d..416910fe59a5f 100644 --- a/tests/baselines/reference/templateLiteralTypes3.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes3.errors.txt @@ -221,4 +221,12 @@ templateLiteralTypes3.ts(141,9): error TS2367: This comparison appears to be uni // Repro from #52685 type Boom = 'abc' | 'def' | `a${string}` | Lowercase; + + // Repro from #56582 + + function a() { + let x: keyof T & string | `-${keyof T & string}`; + x = "id"; + x = "-id"; + } \ No newline at end of file diff --git a/tests/baselines/reference/templateLiteralTypes3.js b/tests/baselines/reference/templateLiteralTypes3.js index 83e6f2b0d05e9..8b79c69810e3c 100644 --- a/tests/baselines/reference/templateLiteralTypes3.js +++ b/tests/baselines/reference/templateLiteralTypes3.js @@ -195,6 +195,14 @@ function ft1(t: T, u: Uppercase, u1: Uppercase<`1.${T}.3`>, // Repro from #52685 type Boom = 'abc' | 'def' | `a${string}` | Lowercase; + +// Repro from #56582 + +function a() { + let x: keyof T & string | `-${keyof T & string}`; + x = "id"; + x = "-id"; +} //// [templateLiteralTypes3.js] @@ -291,6 +299,12 @@ function ft1(t, u, u1, u2) { spread("1.".concat(u, ".3"), "1.".concat(u, ".4")); spread(u1, u2); } +// Repro from #56582 +function a() { + var x; + x = "id"; + x = "-id"; +} //// [templateLiteralTypes3.d.ts] @@ -363,3 +377,6 @@ declare function noSpread

(args: P[]): P; declare function spread

(...args: P[]): P; declare function ft1(t: T, u: Uppercase, u1: Uppercase<`1.${T}.3`>, u2: Uppercase<`1.${T}.4`>): void; type Boom = 'abc' | 'def' | `a${string}` | Lowercase; +declare function a(): void; diff --git a/tests/baselines/reference/templateLiteralTypes3.symbols b/tests/baselines/reference/templateLiteralTypes3.symbols index 1259e9f56b02f..bead567c4a85f 100644 --- a/tests/baselines/reference/templateLiteralTypes3.symbols +++ b/tests/baselines/reference/templateLiteralTypes3.symbols @@ -588,3 +588,22 @@ type Boom = 'abc' | 'def' | `a${string}` | Lowercase; >Boom : Symbol(Boom, Decl(templateLiteralTypes3.ts, 189, 1)) >Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --)) +// Repro from #56582 + +function a() { +>a : Symbol(a, Decl(templateLiteralTypes3.ts, 193, 61)) +>T : Symbol(T, Decl(templateLiteralTypes3.ts, 197, 11)) +>id : Symbol(id, Decl(templateLiteralTypes3.ts, 197, 22)) + + let x: keyof T & string | `-${keyof T & string}`; +>x : Symbol(x, Decl(templateLiteralTypes3.ts, 198, 7)) +>T : Symbol(T, Decl(templateLiteralTypes3.ts, 197, 11)) +>T : Symbol(T, Decl(templateLiteralTypes3.ts, 197, 11)) + + x = "id"; +>x : Symbol(x, Decl(templateLiteralTypes3.ts, 198, 7)) + + x = "-id"; +>x : Symbol(x, Decl(templateLiteralTypes3.ts, 198, 7)) +} + diff --git a/tests/baselines/reference/templateLiteralTypes3.types b/tests/baselines/reference/templateLiteralTypes3.types index 67115bf715ab6..a37862c886cf6 100644 --- a/tests/baselines/reference/templateLiteralTypes3.types +++ b/tests/baselines/reference/templateLiteralTypes3.types @@ -601,3 +601,23 @@ function ft1(t: T, u: Uppercase, u1: Uppercase<`1.${T}.3`>, type Boom = 'abc' | 'def' | `a${string}` | Lowercase; >Boom : `a${string}` | Lowercase | "def" +// Repro from #56582 + +function a() { +>a : () => void +>id : string + + let x: keyof T & string | `-${keyof T & string}`; +>x : (keyof T & string) | `-${keyof T & string}` + + x = "id"; +>x = "id" : "id" +>x : (keyof T & string) | `-${keyof T & string}` +>"id" : "id" + + x = "-id"; +>x = "-id" : "-id" +>x : (keyof T & string) | `-${keyof T & string}` +>"-id" : "-id" +} + diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes3.ts b/tests/cases/conformance/types/literal/templateLiteralTypes3.ts index 3103c48201d0b..73adca7da763a 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes3.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes3.ts @@ -195,3 +195,11 @@ function ft1(t: T, u: Uppercase, u1: Uppercase<`1.${T}.3`>, // Repro from #52685 type Boom = 'abc' | 'def' | `a${string}` | Lowercase; + +// Repro from #56582 + +function a() { + let x: keyof T & string | `-${keyof T & string}`; + x = "id"; + x = "-id"; +}