Skip to content

Commit 198754f

Browse files
committed
feat: add typeof modifier in template string
1 parent 0353053 commit 198754f

File tree

4 files changed

+16
-5
lines changed

4 files changed

+16
-5
lines changed

src/compiler/checker.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -13439,12 +13439,15 @@ namespace ts {
1343913439
let text = texts[0];
1344013440
for (let i = 0; i < types.length; i++) {
1344113441
const t = types[i];
13442-
if (t.flags & TypeFlags.Literal) {
13443-
const s = applyTemplateCasing(getTemplateStringForType(t) || "", casings[i]);
13442+
const casingType = casings[i];
13443+
const isGeneric = isGenericIndexType(t);
13444+
const resolvable = (t.flags & TypeFlags.Literal) || (!isGeneric && casingType === TemplateCasing.TypeOf);
13445+
if (resolvable) {
13446+
const s = applyTemplateCasing(getTemplateStringForType(t, casingType) || "", casingType);
1344413447
text += s;
1344513448
text += texts[i + 1];
1344613449
}
13447-
else if (isGenericIndexType(t)) {
13450+
else if (isGeneric) {
1344813451
newTypes.push(t);
1344913452
newCasings.push(casings[i]);
1345013453
newTexts.push(text);
@@ -13466,7 +13469,10 @@ namespace ts {
1346613469
return type;
1346713470
}
1346813471

13469-
function getTemplateStringForType(type: Type) {
13472+
function getTemplateStringForType(type: Type, casing: TemplateCasing) {
13473+
if (casing === TemplateCasing.TypeOf) {
13474+
return getTypeNameForErrorDisplay(type);
13475+
}
1347013476
return type.flags & TypeFlags.StringLiteral ? (<StringLiteralType>type).value :
1347113477
type.flags & TypeFlags.NumberLiteral ? "" + (<NumberLiteralType>type).value :
1347213478
type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((<BigIntLiteralType>type).value) :
@@ -31424,7 +31430,9 @@ namespace ts {
3142431430
getTypeFromTypeNode(node);
3142531431
for (const span of node.templateSpans) {
3142631432
const type = getTypeFromTypeNode(span.type);
31427-
checkTypeAssignableTo(type, templateConstraintType, span.type);
31433+
if (span.casing !== TemplateCasing.TypeOf) {
31434+
checkTypeAssignableTo(type, templateConstraintType, span.type);
31435+
}
3142831436
if (!everyType(type, t => !!(t.flags & TypeFlags.Literal) || isGenericIndexType(t))) {
3142931437
error(span.type, Diagnostics.Template_type_argument_0_is_not_literal_type_or_a_generic_type, typeToString(type));
3143031438
}

src/compiler/emitter.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,7 @@ namespace ts {
20132013
node.casing === TemplateCasing.Lowercase ? "lowercase" :
20142014
node.casing === TemplateCasing.Capitalize ? "capitalize" :
20152015
node.casing === TemplateCasing.Uncapitalize ? "uncapitalize" :
2016+
node.casing === TemplateCasing.TypeOf ? "typeof" :
20162017
undefined;
20172018
if (keyword) {
20182019
writeKeyword(keyword);

src/compiler/parser.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2621,6 +2621,7 @@ namespace ts {
26212621
parseOptional(SyntaxKind.LowercaseKeyword) ? TemplateCasing.Lowercase :
26222622
parseOptional(SyntaxKind.CapitalizeKeyword) ? TemplateCasing.Capitalize :
26232623
parseOptional(SyntaxKind.UncapitalizeKeyword) ? TemplateCasing.Uncapitalize :
2624+
parseOptional(SyntaxKind.TypeOfKeyword) ? TemplateCasing.TypeOf :
26242625
TemplateCasing.None;
26252626
}
26262627

src/compiler/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1672,6 +1672,7 @@ namespace ts {
16721672
Lowercase,
16731673
Capitalize,
16741674
Uncapitalize,
1675+
TypeOf,
16751676
}
16761677

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

0 commit comments

Comments
 (0)