Fix constant evaluation of template string expressions (#58500)

This commit is contained in:
Anders Hejlsberg 2024-05-14 03:44:05 -10:00 committed by GitHub
parent e51cbc8764
commit d90e8e7eca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 116 additions and 2 deletions

View File

@ -39560,11 +39560,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
texts.push(span.literal.text);
types.push(isTypeAssignableTo(type, templateConstraintType) ? type : stringType);
}
const evaluated = node.parent.kind !== SyntaxKind.TaggedTemplateExpression && evaluate(node).value;
if (evaluated) {
return getFreshTypeOfLiteralType(getStringLiteralType(evaluated));
}
if (isConstContext(node) || isTemplateLiteralContext(node) || someType(getContextualType(node, /*contextFlags*/ undefined) || unknownType, isTemplateLiteralContextualType)) {
return getTemplateLiteralType(texts, types);
}
const evaluated = node.parent.kind !== SyntaxKind.TaggedTemplateExpression && evaluate(node).value;
return evaluated ? getFreshTypeOfLiteralType(getStringLiteralType(evaluated)) : stringType;
return stringType;
}
function isTemplateLiteralContextualType(type: Type): boolean {

View File

@ -0,0 +1,36 @@
//// [tests/cases/compiler/templateLiteralConstantEvaluation.ts] ////
=== templateLiteralConstantEvaluation.ts ===
// https://github.com/microsoft/TypeScript/issues/58494
function fn<T>(arg: T): T {
>fn : Symbol(fn, Decl(templateLiteralConstantEvaluation.ts, 0, 0))
>T : Symbol(T, Decl(templateLiteralConstantEvaluation.ts, 2, 12))
>arg : Symbol(arg, Decl(templateLiteralConstantEvaluation.ts, 2, 15))
>T : Symbol(T, Decl(templateLiteralConstantEvaluation.ts, 2, 12))
>T : Symbol(T, Decl(templateLiteralConstantEvaluation.ts, 2, 12))
return arg;
>arg : Symbol(arg, Decl(templateLiteralConstantEvaluation.ts, 2, 15))
}
const a = '1';
>a : Symbol(a, Decl(templateLiteralConstantEvaluation.ts, 6, 5))
const b = a + ' 2';
>b : Symbol(b, Decl(templateLiteralConstantEvaluation.ts, 7, 5))
>a : Symbol(a, Decl(templateLiteralConstantEvaluation.ts, 6, 5))
const c = `${b} 3`;
>c : Symbol(c, Decl(templateLiteralConstantEvaluation.ts, 8, 5))
>b : Symbol(b, Decl(templateLiteralConstantEvaluation.ts, 7, 5))
const d = `${b} 3` as const;
>d : Symbol(d, Decl(templateLiteralConstantEvaluation.ts, 9, 5))
>b : Symbol(b, Decl(templateLiteralConstantEvaluation.ts, 7, 5))
>const : Symbol(const)
fn(`${b} 3`);
>fn : Symbol(fn, Decl(templateLiteralConstantEvaluation.ts, 0, 0))
>b : Symbol(b, Decl(templateLiteralConstantEvaluation.ts, 7, 5))

View File

@ -0,0 +1,60 @@
//// [tests/cases/compiler/templateLiteralConstantEvaluation.ts] ////
=== templateLiteralConstantEvaluation.ts ===
// https://github.com/microsoft/TypeScript/issues/58494
function fn<T>(arg: T): T {
>fn : <T>(arg: T) => T
> : ^ ^^ ^^ ^^^^^
>arg : T
> : ^
return arg;
>arg : T
> : ^
}
const a = '1';
>a : "1"
> : ^^^
>'1' : "1"
> : ^^^
const b = a + ' 2';
>b : string
> : ^^^^^^
>a + ' 2' : string
> : ^^^^^^
>a : "1"
> : ^^^
>' 2' : " 2"
> : ^^^^
const c = `${b} 3`;
>c : "1 2 3"
> : ^^^^^^^
>`${b} 3` : "1 2 3"
> : ^^^^^^^
>b : string
> : ^^^^^^
const d = `${b} 3` as const;
>d : "1 2 3"
> : ^^^^^^^
>`${b} 3` as const : "1 2 3"
> : ^^^^^^^
>`${b} 3` : "1 2 3"
> : ^^^^^^^
>b : string
> : ^^^^^^
fn(`${b} 3`);
>fn(`${b} 3`) : "1 2 3"
> : ^^^^^^^
>fn : <T>(arg: T) => T
> : ^ ^^ ^^ ^^^^^^
>`${b} 3` : "1 2 3"
> : ^^^^^^^
>b : string
> : ^^^^^^

View File

@ -0,0 +1,15 @@
// @strict: true
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/58494
function fn<T>(arg: T): T {
return arg;
}
const a = '1';
const b = a + ' 2';
const c = `${b} 3`;
const d = `${b} 3` as const;
fn(`${b} 3`);