Skip to content

Commit

Permalink
fix(48034): Get a literal string of type intersection in a template l…
Browse files Browse the repository at this point in the history
…iteral type (#48044)
  • Loading branch information
islandryu authored Mar 22, 2022
1 parent 6cb58d3 commit bf0eef4
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
33 changes: 33 additions & 0 deletions tests/baselines/reference/templateLiteralIntersection.js
Original file line number Diff line number Diff line change
@@ -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';
80 changes: 80 additions & 0 deletions tests/baselines/reference/templateLiteralIntersection.symbols
Original file line number Diff line number Diff line change
@@ -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))

64 changes: 64 additions & 0 deletions tests/baselines/reference/templateLiteralIntersection.types
Original file line number Diff line number Diff line change
@@ -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"

28 changes: 28 additions & 0 deletions tests/cases/compiler/templateLiteralIntersection.ts
Original file line number Diff line number Diff line change
@@ -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}`;

0 comments on commit bf0eef4

Please sign in to comment.