Skip to content

Commit f1286b6

Browse files
committed
feat: add typeof modifier in template string
1 parent 2a9f067 commit f1286b6

File tree

4 files changed

+16
-5
lines changed

4 files changed

+16
-5
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13482,12 +13482,15 @@ namespace ts {
1348213482
let text = texts[0];
1348313483
for (let i = 0; i < types.length; i++) {
1348413484
const t = types[i];
13485-
if (t.flags & TypeFlags.Literal) {
13486-
const s = applyTemplateCasing(getTemplateStringForType(t) || "", casings[i]);
13485+
const casingType = casings[i];
13486+
const isGeneric = isGenericIndexType(t);
13487+
const resolvable = (t.flags & TypeFlags.Literal) || (!isGeneric && casingType === TemplateCasing.TypeOf);
13488+
if (resolvable) {
13489+
const s = applyTemplateCasing(getTemplateStringForType(t, casingType) || "", casingType);
1348713490
text += s;
1348813491
text += texts[i + 1];
1348913492
}
13490-
else if (isGenericIndexType(t)) {
13493+
else if (isGeneric) {
1349113494
newTypes.push(t);
1349213495
newCasings.push(casings[i]);
1349313496
newTexts.push(text);
@@ -13509,7 +13512,10 @@ namespace ts {
1350913512
return type;
1351013513
}
1351113514

13512-
function getTemplateStringForType(type: Type) {
13515+
function getTemplateStringForType(type: Type, casing: TemplateCasing) {
13516+
if (casing === TemplateCasing.TypeOf) {
13517+
return getTypeNameForErrorDisplay(type);
13518+
}
1351313519
return type.flags & TypeFlags.StringLiteral ? (<StringLiteralType>type).value :
1351413520
type.flags & TypeFlags.NumberLiteral ? "" + (<NumberLiteralType>type).value :
1351513521
type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((<BigIntLiteralType>type).value) :
@@ -31518,7 +31524,9 @@ namespace ts {
3151831524
getTypeFromTypeNode(node);
3151931525
for (const span of node.templateSpans) {
3152031526
const type = getTypeFromTypeNode(span.type);
31521-
checkTypeAssignableTo(type, templateConstraintType, span.type);
31527+
if (span.casing !== TemplateCasing.TypeOf) {
31528+
checkTypeAssignableTo(type, templateConstraintType, span.type);
31529+
}
3152231530
if (!everyType(type, t => !!(t.flags & TypeFlags.Literal) || isGenericIndexType(t))) {
3152331531
error(span.type, Diagnostics.Template_literal_type_argument_0_is_not_literal_type_or_a_generic_type, typeToString(type));
3152431532
}

src/compiler/emitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,7 @@ namespace ts {
20192019
node.casing === TemplateCasing.Lowercase ? "lowercase" :
20202020
node.casing === TemplateCasing.Capitalize ? "capitalize" :
20212021
node.casing === TemplateCasing.Uncapitalize ? "uncapitalize" :
2022+
node.casing === TemplateCasing.TypeOf ? "typeof" :
20222023
undefined;
20232024
if (keyword) {
20242025
writeKeyword(keyword);

src/compiler/parser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,6 +2629,7 @@ namespace ts {
26292629
parseOptional(SyntaxKind.LowercaseKeyword) ? TemplateCasing.Lowercase :
26302630
parseOptional(SyntaxKind.CapitalizeKeyword) ? TemplateCasing.Capitalize :
26312631
parseOptional(SyntaxKind.UncapitalizeKeyword) ? TemplateCasing.Uncapitalize :
2632+
parseOptional(SyntaxKind.TypeOfKeyword) ? TemplateCasing.TypeOf :
26322633
TemplateCasing.None;
26332634
}
26342635

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,7 @@ namespace ts {
16741674
Lowercase,
16751675
Capitalize,
16761676
Uncapitalize,
1677+
TypeOf,
16771678
}
16781679

16791680
// Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.

0 commit comments

Comments
 (0)