From e32efd44135864de44d4a94d0d2469664b966ac2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 13 Apr 2021 11:18:57 -1000 Subject: [PATCH 1/2] Add missing constraint check for template literal types --- src/compiler/checker.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 781afe2cf9a84..64945acf33200 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18402,6 +18402,16 @@ namespace ts { return result; } } + else if (source.flags & TypeFlags.TemplateLiteral) { + if (!(target.flags & TypeFlags.TemplateLiteral)) { + const baseConstraint = getBaseConstraintOfType(source); + const constraint = baseConstraint && baseConstraint !== source ? baseConstraint : stringType; + if (result = isRelatedTo(constraint, target, reportErrors)) { + resetErrorInfo(saveErrorInfo); + return result; + } + } + } else if (source.flags & TypeFlags.StringMapping) { if (target.flags & TypeFlags.StringMapping && (source).symbol === (target).symbol) { if (result = isRelatedTo((source).type, (target).type, reportErrors)) { From 2ba13cb947b3e5fe96f940da845181e13fefc2ed Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 13 Apr 2021 11:21:48 -1000 Subject: [PATCH 2/2] Add regression test --- .../templateLiteralTypes3.errors.txt | 12 +++++++++ .../reference/templateLiteralTypes3.js | 18 +++++++++++++ .../reference/templateLiteralTypes3.symbols | 27 +++++++++++++++++++ .../reference/templateLiteralTypes3.types | 16 +++++++++++ .../types/literal/templateLiteralTypes3.ts | 12 +++++++++ 5 files changed, 85 insertions(+) diff --git a/tests/baselines/reference/templateLiteralTypes3.errors.txt b/tests/baselines/reference/templateLiteralTypes3.errors.txt index 67fef27292ef9..4e177c8d225ec 100644 --- a/tests/baselines/reference/templateLiteralTypes3.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes3.errors.txt @@ -126,4 +126,16 @@ tests/cases/conformance/types/literal/templateLiteralTypes3.ts(74,5): error TS23 const value2 = "abc"; const templated2: Templated = `${value2} abc` as const; + + // Repro from #43620 + + type Prefixes = "foo" | "bar"; + + type AllPrefixData = "foo:baz" | "bar:baz"; + + type PrefixData

= `${P}:baz`; + + interface ITest

> { + blah: string; + } \ No newline at end of file diff --git a/tests/baselines/reference/templateLiteralTypes3.js b/tests/baselines/reference/templateLiteralTypes3.js index f57d98f980941..7557ad9f47462 100644 --- a/tests/baselines/reference/templateLiteralTypes3.js +++ b/tests/baselines/reference/templateLiteralTypes3.js @@ -104,6 +104,18 @@ const templated1: Templated = `${value1} abc` as const; const value2 = "abc"; const templated2: Templated = `${value2} abc` as const; + +// Repro from #43620 + +type Prefixes = "foo" | "bar"; + +type AllPrefixData = "foo:baz" | "bar:baz"; + +type PrefixData

= `${P}:baz`; + +interface ITest

> { + blah: string; +} //// [templateLiteralTypes3.js] @@ -198,3 +210,9 @@ declare const value1: string; declare const templated1: Templated; declare const value2 = "abc"; declare const templated2: Templated; +declare type Prefixes = "foo" | "bar"; +declare type AllPrefixData = "foo:baz" | "bar:baz"; +declare type PrefixData

= `${P}:baz`; +interface ITest

> { + blah: string; +} diff --git a/tests/baselines/reference/templateLiteralTypes3.symbols b/tests/baselines/reference/templateLiteralTypes3.symbols index f51bf02e74747..2d74d50a3d909 100644 --- a/tests/baselines/reference/templateLiteralTypes3.symbols +++ b/tests/baselines/reference/templateLiteralTypes3.symbols @@ -342,3 +342,30 @@ const templated2: Templated = `${value2} abc` as const; >Templated : Symbol(Templated, Decl(templateLiteralTypes3.ts, 93, 29)) >value2 : Symbol(value2, Decl(templateLiteralTypes3.ts, 103, 5)) +// Repro from #43620 + +type Prefixes = "foo" | "bar"; +>Prefixes : Symbol(Prefixes, Decl(templateLiteralTypes3.ts, 104, 55)) + +type AllPrefixData = "foo:baz" | "bar:baz"; +>AllPrefixData : Symbol(AllPrefixData, Decl(templateLiteralTypes3.ts, 108, 30)) + +type PrefixData

= `${P}:baz`; +>PrefixData : Symbol(PrefixData, Decl(templateLiteralTypes3.ts, 110, 43)) +>P : Symbol(P, Decl(templateLiteralTypes3.ts, 112, 16)) +>Prefixes : Symbol(Prefixes, Decl(templateLiteralTypes3.ts, 104, 55)) +>P : Symbol(P, Decl(templateLiteralTypes3.ts, 112, 16)) + +interface ITest

> { +>ITest : Symbol(ITest, Decl(templateLiteralTypes3.ts, 112, 49)) +>P : Symbol(P, Decl(templateLiteralTypes3.ts, 114, 16)) +>Prefixes : Symbol(Prefixes, Decl(templateLiteralTypes3.ts, 104, 55)) +>E : Symbol(E, Decl(templateLiteralTypes3.ts, 114, 35)) +>AllPrefixData : Symbol(AllPrefixData, Decl(templateLiteralTypes3.ts, 108, 30)) +>PrefixData : Symbol(PrefixData, Decl(templateLiteralTypes3.ts, 110, 43)) +>P : Symbol(P, Decl(templateLiteralTypes3.ts, 114, 16)) + + blah: string; +>blah : Symbol(ITest.blah, Decl(templateLiteralTypes3.ts, 114, 78)) +} + diff --git a/tests/baselines/reference/templateLiteralTypes3.types b/tests/baselines/reference/templateLiteralTypes3.types index 2243b25218abc..7fd34b2337de0 100644 --- a/tests/baselines/reference/templateLiteralTypes3.types +++ b/tests/baselines/reference/templateLiteralTypes3.types @@ -363,3 +363,19 @@ const templated2: Templated = `${value2} abc` as const; >`${value2} abc` : "abc abc" >value2 : "abc" +// Repro from #43620 + +type Prefixes = "foo" | "bar"; +>Prefixes : Prefixes + +type AllPrefixData = "foo:baz" | "bar:baz"; +>AllPrefixData : AllPrefixData + +type PrefixData

= `${P}:baz`; +>PrefixData : `${P}:baz` + +interface ITest

> { + blah: string; +>blah : string +} + diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes3.ts b/tests/cases/conformance/types/literal/templateLiteralTypes3.ts index 81ab2427963cd..fa29ad779ab5b 100644 --- a/tests/cases/conformance/types/literal/templateLiteralTypes3.ts +++ b/tests/cases/conformance/types/literal/templateLiteralTypes3.ts @@ -106,3 +106,15 @@ const templated1: Templated = `${value1} abc` as const; const value2 = "abc"; const templated2: Templated = `${value2} abc` as const; + +// Repro from #43620 + +type Prefixes = "foo" | "bar"; + +type AllPrefixData = "foo:baz" | "bar:baz"; + +type PrefixData

= `${P}:baz`; + +interface ITest

> { + blah: string; +}