fix(48034): Get a literal string of type intersection in a template literal type (#48044)

This commit is contained in:
islandryu
2022-03-22 13:38:24 -07:00
committed by GitHub
parent 6cb58d382f
commit bf0eef4353
5 changed files with 218 additions and 5 deletions
+13 -5
View File
@@ -15256,24 +15256,32 @@ 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 {
else if (t.flags & TypeFlags.Intersection) {
const added = addSpans(texts[i + 1], (t as IntersectionType).types);
if (!added) return false;
}
else if (isTextsArray) {
return false;
}
}
@@ -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 extends string> =
`${T & { foo: string }}`
type OriginD = `${MixD<A & { foo: string }> & { 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';
@@ -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<T extends string> =
>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<A & { foo: string }> & { 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))
@@ -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<T extends string> =
>MixD : `${T & { foo: string; }}`
`${T & { foo: string }}`
>foo : string
type OriginD = `${MixD<A & { foo: string }> & { 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"
@@ -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 extends string> =
`${T & { foo: string }}`
type OriginD = `${MixD<A & { foo: string }> & { foo: string }}`;
type E = `${A & {}}`;
type MixE = E & {}
type OriginE = `${MixE}`
type OriginF = `${A}foo${A}`;