From 4c834cf6e02bc71cf2d798279487bdabedcfa6b8 Mon Sep 17 00:00:00 2001 From: islandryu Date: Sat, 26 Feb 2022 14:55:20 +0900 Subject: [PATCH 1/4] Change to get the literal type in the intersection type in the template literal type --- src/compiler/checker.ts | 19 +++++ .../reference/templateLiteralIntersection.js | 33 ++++++++ .../templateLiteralIntersection.symbols | 80 +++++++++++++++++++ .../templateLiteralIntersection.types | 64 +++++++++++++++ .../compiler/templateLiteralIntersection.ts | 28 +++++++ 5 files changed, 224 insertions(+) create mode 100644 tests/baselines/reference/templateLiteralIntersection.js create mode 100644 tests/baselines/reference/templateLiteralIntersection.symbols create mode 100644 tests/baselines/reference/templateLiteralIntersection.types create mode 100644 tests/cases/compiler/templateLiteralIntersection.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7079ecf8a48f7..c6571c19322bd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15134,12 +15134,31 @@ namespace ts { newTexts.push(text); text = texts[i + 1]; } + else if (t.flags & TypeFlags.Intersection){ + const addText = getTemplateStringForInterSectionType((t as IntersectionType)); + if (!addText) return false; + text += addText; + text += texts[i + 1]; + } else { return false; } } return true; } + + function getTemplateStringForInterSectionType(type: IntersectionType): string | undefined { + for (const t of type.types) { + if (t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) { + return getTemplateStringForType(t) || ""; + } + else if (t.flags & TypeFlags.TemplateLiteral) { + if (!addSpans((t as TemplateLiteralType).texts, (t as TemplateLiteralType).types)) continue; + return (t as TemplateLiteralType).texts[0]; + } + } + return undefined; + } } function getTemplateStringForType(type: Type) { diff --git a/tests/baselines/reference/templateLiteralIntersection.js b/tests/baselines/reference/templateLiteralIntersection.js new file mode 100644 index 0000000000000..24a5a684a2e0f --- /dev/null +++ b/tests/baselines/reference/templateLiteralIntersection.js @@ -0,0 +1,33 @@ +//// [templateLiteralIntersection.ts] +// https://github.com/microsoft/TypeScript/issues/48034 +const a = 'a' + +type A = typeof a +type MixA = A & {foo: string} + +type OriginA1 = `${A}` +type OriginA2 = `${MixA}` + +type B = `${typeof a}` +type MixB = B & { foo: string } + +type OriginB1 = `${B}` +type OriginB2 = `${MixB}` + +type MixC = { foo: string } & A + +type OriginC = `${MixC}` + +type MixD = + `${T & { foo: string }}` +type OriginD = `${MixD & { foo: string }}`; + +type E = `${A & {}}`; +type MixE = E & {} +type OriginE = `${MixE}` + +type OriginF = `${A}foo${A}`; + +//// [templateLiteralIntersection.js] +// https://github.com/microsoft/TypeScript/issues/48034 +var a = 'a'; diff --git a/tests/baselines/reference/templateLiteralIntersection.symbols b/tests/baselines/reference/templateLiteralIntersection.symbols new file mode 100644 index 0000000000000..031b081d203db --- /dev/null +++ b/tests/baselines/reference/templateLiteralIntersection.symbols @@ -0,0 +1,80 @@ +=== tests/cases/compiler/templateLiteralIntersection.ts === +// https://github.com/microsoft/TypeScript/issues/48034 +const a = 'a' +>a : Symbol(a, Decl(templateLiteralIntersection.ts, 1, 5)) + +type A = typeof a +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) +>a : Symbol(a, Decl(templateLiteralIntersection.ts, 1, 5)) + +type MixA = A & {foo: string} +>MixA : Symbol(MixA, Decl(templateLiteralIntersection.ts, 3, 17)) +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) +>foo : Symbol(foo, Decl(templateLiteralIntersection.ts, 4, 17)) + +type OriginA1 = `${A}` +>OriginA1 : Symbol(OriginA1, Decl(templateLiteralIntersection.ts, 4, 29)) +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) + +type OriginA2 = `${MixA}` +>OriginA2 : Symbol(OriginA2, Decl(templateLiteralIntersection.ts, 6, 22)) +>MixA : Symbol(MixA, Decl(templateLiteralIntersection.ts, 3, 17)) + +type B = `${typeof a}` +>B : Symbol(B, Decl(templateLiteralIntersection.ts, 7, 25)) +>a : Symbol(a, Decl(templateLiteralIntersection.ts, 1, 5)) + +type MixB = B & { foo: string } +>MixB : Symbol(MixB, Decl(templateLiteralIntersection.ts, 9, 22)) +>B : Symbol(B, Decl(templateLiteralIntersection.ts, 7, 25)) +>foo : Symbol(foo, Decl(templateLiteralIntersection.ts, 10, 17)) + +type OriginB1 = `${B}` +>OriginB1 : Symbol(OriginB1, Decl(templateLiteralIntersection.ts, 10, 31)) +>B : Symbol(B, Decl(templateLiteralIntersection.ts, 7, 25)) + +type OriginB2 = `${MixB}` +>OriginB2 : Symbol(OriginB2, Decl(templateLiteralIntersection.ts, 12, 22)) +>MixB : Symbol(MixB, Decl(templateLiteralIntersection.ts, 9, 22)) + +type MixC = { foo: string } & A +>MixC : Symbol(MixC, Decl(templateLiteralIntersection.ts, 13, 25)) +>foo : Symbol(foo, Decl(templateLiteralIntersection.ts, 15, 13)) +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) + +type OriginC = `${MixC}` +>OriginC : Symbol(OriginC, Decl(templateLiteralIntersection.ts, 15, 31)) +>MixC : Symbol(MixC, Decl(templateLiteralIntersection.ts, 13, 25)) + +type MixD = +>MixD : Symbol(MixD, Decl(templateLiteralIntersection.ts, 17, 24)) +>T : Symbol(T, Decl(templateLiteralIntersection.ts, 19, 10)) + + `${T & { foo: string }}` +>T : Symbol(T, Decl(templateLiteralIntersection.ts, 19, 10)) +>foo : Symbol(foo, Decl(templateLiteralIntersection.ts, 20, 12)) + +type OriginD = `${MixD & { foo: string }}`; +>OriginD : Symbol(OriginD, Decl(templateLiteralIntersection.ts, 20, 28)) +>MixD : Symbol(MixD, Decl(templateLiteralIntersection.ts, 17, 24)) +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) +>foo : Symbol(foo, Decl(templateLiteralIntersection.ts, 21, 28)) +>foo : Symbol(foo, Decl(templateLiteralIntersection.ts, 21, 47)) + +type E = `${A & {}}`; +>E : Symbol(E, Decl(templateLiteralIntersection.ts, 21, 64)) +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) + +type MixE = E & {} +>MixE : Symbol(MixE, Decl(templateLiteralIntersection.ts, 23, 21)) +>E : Symbol(E, Decl(templateLiteralIntersection.ts, 21, 64)) + +type OriginE = `${MixE}` +>OriginE : Symbol(OriginE, Decl(templateLiteralIntersection.ts, 24, 18)) +>MixE : Symbol(MixE, Decl(templateLiteralIntersection.ts, 23, 21)) + +type OriginF = `${A}foo${A}`; +>OriginF : Symbol(OriginF, Decl(templateLiteralIntersection.ts, 25, 24)) +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) +>A : Symbol(A, Decl(templateLiteralIntersection.ts, 1, 13)) + diff --git a/tests/baselines/reference/templateLiteralIntersection.types b/tests/baselines/reference/templateLiteralIntersection.types new file mode 100644 index 0000000000000..d675ad0e0eb74 --- /dev/null +++ b/tests/baselines/reference/templateLiteralIntersection.types @@ -0,0 +1,64 @@ +=== tests/cases/compiler/templateLiteralIntersection.ts === +// https://github.com/microsoft/TypeScript/issues/48034 +const a = 'a' +>a : "a" +>'a' : "a" + +type A = typeof a +>A : "a" +>a : "a" + +type MixA = A & {foo: string} +>MixA : MixA +>foo : string + +type OriginA1 = `${A}` +>OriginA1 : "a" + +type OriginA2 = `${MixA}` +>OriginA2 : "a" + +type B = `${typeof a}` +>B : "a" +>a : "a" + +type MixB = B & { foo: string } +>MixB : MixB +>foo : string + +type OriginB1 = `${B}` +>OriginB1 : "a" + +type OriginB2 = `${MixB}` +>OriginB2 : "a" + +type MixC = { foo: string } & A +>MixC : MixC +>foo : string + +type OriginC = `${MixC}` +>OriginC : "a" + +type MixD = +>MixD : `${T & { foo: string; }}` + + `${T & { foo: string }}` +>foo : string + +type OriginD = `${MixD & { foo: string }}`; +>OriginD : "a" +>foo : string +>foo : string + +type E = `${A & {}}`; +>E : "a" + +type MixE = E & {} +>MixE : MixE + +type OriginE = `${MixE}` +>OriginE : "a" + +type OriginF = `${A}foo${A}`; +>OriginF : "afooa" + diff --git a/tests/cases/compiler/templateLiteralIntersection.ts b/tests/cases/compiler/templateLiteralIntersection.ts new file mode 100644 index 0000000000000..9a17d16bc2b2f --- /dev/null +++ b/tests/cases/compiler/templateLiteralIntersection.ts @@ -0,0 +1,28 @@ +// https://github.com/microsoft/TypeScript/issues/48034 +const a = 'a' + +type A = typeof a +type MixA = A & {foo: string} + +type OriginA1 = `${A}` +type OriginA2 = `${MixA}` + +type B = `${typeof a}` +type MixB = B & { foo: string } + +type OriginB1 = `${B}` +type OriginB2 = `${MixB}` + +type MixC = { foo: string } & A + +type OriginC = `${MixC}` + +type MixD = + `${T & { foo: string }}` +type OriginD = `${MixD & { foo: string }}`; + +type E = `${A & {}}`; +type MixE = E & {} +type OriginE = `${MixE}` + +type OriginF = `${A}foo${A}`; \ No newline at end of file From ac28982919a450ddbac7b696eba892b9ee960ed4 Mon Sep 17 00:00:00 2001 From: islandryu Date: Fri, 18 Mar 2022 20:25:52 +0900 Subject: [PATCH 2/4] Function Commonality --- src/compiler/checker.ts | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6571c19322bd..bf9ae0ec67864 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15117,48 +15117,42 @@ namespace ts { } return type; - function addSpans(texts: readonly string[], types: readonly Type[]): boolean { + function addSpans(texts: readonly string[] | string, types: readonly Type[]): boolean { + const isTextsArray = isArray(texts); for (let i = 0; i < types.length; i++) { const t = types[i]; + const addText = isTextsArray ? texts[i + 1] : texts; if (t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) { text += getTemplateStringForType(t) || ""; - text += texts[i + 1]; + text += addText; + if (!isTextsArray) return true; } else if (t.flags & TypeFlags.TemplateLiteral) { text += (t as TemplateLiteralType).texts[0]; if (!addSpans((t as TemplateLiteralType).texts, (t as TemplateLiteralType).types)) return false; - text += texts[i + 1]; + text += addText; + if (!isTextsArray) return true; } else if (isGenericIndexType(t) || isPatternLiteralPlaceholderType(t)) { newTypes.push(t); newTexts.push(text); - text = texts[i + 1]; + text = addText; } - else if (t.flags & TypeFlags.Intersection){ - const addText = getTemplateStringForInterSectionType((t as IntersectionType)); + else if (t.flags & TypeFlags.Intersection) { + const addText = addSpans(texts[i + 1], (t as IntersectionType).types); if (!addText) return false; - text += addText; - text += texts[i + 1]; } else { - return false; + if (isTextsArray) { + return false; + } + else { + continue; + } } } return true; } - - function getTemplateStringForInterSectionType(type: IntersectionType): string | undefined { - for (const t of type.types) { - if (t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) { - return getTemplateStringForType(t) || ""; - } - else if (t.flags & TypeFlags.TemplateLiteral) { - if (!addSpans((t as TemplateLiteralType).texts, (t as TemplateLiteralType).types)) continue; - return (t as TemplateLiteralType).texts[0]; - } - } - return undefined; - } } function getTemplateStringForType(type: Type) { From dc210b67681b0e60690c0ef1ec4f85a488ad444e Mon Sep 17 00:00:00 2001 From: islandryu Date: Mon, 21 Mar 2022 14:16:29 +0900 Subject: [PATCH 3/4] fix ifstatement --- src/compiler/checker.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bf9ae0ec67864..86d6b2e48b20f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15142,13 +15142,8 @@ namespace ts { const addText = addSpans(texts[i + 1], (t as IntersectionType).types); if (!addText) return false; } - else { - if (isTextsArray) { - return false; - } - else { - continue; - } + else if (isTextsArray) { + return false; } } return true; From 30b8601e7bcfe78ae72118678f3fda01904be672 Mon Sep 17 00:00:00 2001 From: islandryu Date: Mon, 21 Mar 2022 14:18:40 +0900 Subject: [PATCH 4/4] fix variablename --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 86d6b2e48b20f..ef0ee06bfd81c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15139,8 +15139,8 @@ namespace ts { text = addText; } else if (t.flags & TypeFlags.Intersection) { - const addText = addSpans(texts[i + 1], (t as IntersectionType).types); - if (!addText) return false; + const added = addSpans(texts[i + 1], (t as IntersectionType).types); + if (!added) return false; } else if (isTextsArray) { return false;