Skip to content

Commit e0c3fc6

Browse files
committed
Strip object type tags in template literal placeholders
1 parent b464619 commit e0c3fc6

File tree

1 file changed

+16
-17
lines changed

1 file changed

+16
-17
lines changed

src/compiler/checker.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17696,7 +17696,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1769617696

1769717697
function addSpans(texts: readonly string[], types: readonly Type[]): boolean {
1769817698
for (let i = 0; i < types.length; i++) {
17699-
const t = types[i];
17699+
const t = stripObjectTypeTags(types[i]);
1770017700
if (t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) {
1770117701
text += getTemplateStringForType(t) || "";
1770217702
text += texts[i + 1];
@@ -17719,6 +17719,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1771917719
}
1772017720
}
1772117721

17722+
function stripObjectTypeTags(type: Type) {
17723+
if (type.flags & TypeFlags.Intersection) {
17724+
const nonObjectTypes = filter((type as IntersectionType).types, t => !(t.flags & TypeFlags.Object));
17725+
if (nonObjectTypes !== (type as IntersectionType).types) {
17726+
return getIntersectionType(nonObjectTypes);
17727+
}
17728+
}
17729+
return type;
17730+
}
17731+
1772217732
function getTemplateStringForType(type: Type) {
1772317733
return type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value :
1772417734
type.flags & TypeFlags.NumberLiteral ? "" + (type as NumberLiteralType).value :
@@ -18052,26 +18062,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1805218062
}
1805318063

1805418064
function isPatternLiteralPlaceholderType(type: Type): boolean {
18055-
if (type.flags & TypeFlags.Intersection) {
18056-
// Return true if the intersection consists of one or more placeholders and zero or
18057-
// more object type tags.
18058-
let seenPlaceholder = false;
18059-
for (const t of (type as IntersectionType).types) {
18060-
if (t.flags & (TypeFlags.Literal | TypeFlags.Nullable) || isPatternLiteralPlaceholderType(t)) {
18061-
seenPlaceholder = true;
18062-
}
18063-
else if (!(t.flags & TypeFlags.Object)) {
18064-
return false;
18065-
}
18066-
}
18067-
return seenPlaceholder;
18068-
}
18069-
return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) || isPatternLiteralType(type);
18065+
return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt) ||
18066+
isPatternLiteralType(type) ||
18067+
type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isPatternLiteralType));
1807018068
}
1807118069

1807218070
function isPatternLiteralType(type: Type) {
1807318071
// A pattern literal type is a template literal or a string mapping type that contains only
18074-
// non-generic pattern literal placeholders.
18072+
// non-generic pattern literal placeholders. Assumptions are made elsewhere that pattern literal
18073+
// contain no generics. For example, pattern literal types can be key types in index signatures.
1807518074
return !!(type.flags & TypeFlags.TemplateLiteral) && every((type as TemplateLiteralType).types, isPatternLiteralPlaceholderType) ||
1807618075
!!(type.flags & TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as StringMappingType).type);
1807718076
}

0 commit comments

Comments
 (0)