Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ import {
isSimpleInlineableExpression,
isSourceFile,
isStatement,
isSyntacticallyString,
isTemplateLiteral,
isTryStatement,
JsxOpeningElement,
Expand Down Expand Up @@ -1922,7 +1923,7 @@ export function transformTypeScript(context: TransformationContext) {
),
valueExpression,
);
const outerAssignment = valueExpression.kind === SyntaxKind.StringLiteral ?
const outerAssignment = isSyntacticallyString(valueExpression) ?
innerAssignment :
factory.createAssignment(
factory.createElementAccessExpression(
Expand Down
19 changes: 19 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10639,3 +10639,22 @@ export function replaceFirstStar(s: string, replacement: string): string {
export function getNameFromImportAttribute(node: ImportAttribute) {
return isIdentifier(node.name) ? node.name.escapedText : escapeLeadingUnderscores(node.name.text);
}

/** @internal */
export function isSyntacticallyString(expr: Expression): boolean {
expr = skipOuterExpressions(expr);
switch (expr.kind) {
case SyntaxKind.BinaryExpression:
const left = (expr as BinaryExpression).left;
const right = (expr as BinaryExpression).right;
return (
(expr as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken &&
(isSyntacticallyString(left) || isSyntacticallyString(right))
);
case SyntaxKind.TemplateExpression:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return true;
}
return false;
}
9 changes: 9 additions & 0 deletions src/testRunner/unittests/services/transpile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -673,4 +673,13 @@ export * as alias from './file';`,
options: { compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ESNext } },
},
);

transpilesCorrectly(
"Syntactically string but non-evaluatable enum members do not get reverse mapping",
// eslint-disable-next-line no-template-curly-in-string
"import { BAR } from './bar'; enum Foo { A = `${BAR}` }",
{
options: { compilerOptions: { target: ts.ScriptTarget.ESNext } },
},
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
computedEnumMemberSyntacticallyString.ts(4,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(5,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(6,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(7,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(8,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.


==== computedEnumMemberSyntacticallyString.ts (5 errors) ====
const BAR = 2..toFixed(0);

enum Foo {
A = `${BAR}`,
~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
B = "2" + BAR,
~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
C = (`${BAR}`),
~~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
D = (`${BAR}}`) as string,
~~~~~~~~~~~~~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
E = `${BAR}`!,
~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/computedEnumMemberSyntacticallyString.ts] ////

//// [computedEnumMemberSyntacticallyString.ts]
const BAR = 2..toFixed(0);

enum Foo {
A = `${BAR}`,
B = "2" + BAR,
C = (`${BAR}`),
D = (`${BAR}}`) as string,
E = `${BAR}`!,
}


//// [computedEnumMemberSyntacticallyString.js]
const BAR = 2..toFixed(0);
var Foo;
(function (Foo) {
Foo["A"] = `${BAR}`;
Foo["B"] = "2" + BAR;
Foo["C"] = (`${BAR}`);
Foo["D"] = (`${BAR}}`);
Foo["E"] = `${BAR}`;
})(Foo || (Foo = {}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
computedEnumMemberSyntacticallyString.ts(4,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(5,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(6,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(7,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
computedEnumMemberSyntacticallyString.ts(8,9): error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.


==== computedEnumMemberSyntacticallyString.ts (5 errors) ====
const BAR = 2..toFixed(0);

enum Foo {
A = `${BAR}`,
~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
B = "2" + BAR,
~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
C = (`${BAR}`),
~~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
D = (`${BAR}}`) as string,
~~~~~~~~~~~~~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
E = `${BAR}`!,
~~~~~~~~~
!!! error TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/computedEnumMemberSyntacticallyString.ts] ////

//// [computedEnumMemberSyntacticallyString.ts]
const BAR = 2..toFixed(0);

enum Foo {
A = `${BAR}`,
B = "2" + BAR,
C = (`${BAR}`),
D = (`${BAR}}`) as string,
E = `${BAR}`!,
}


//// [computedEnumMemberSyntacticallyString.js]
const BAR = 2..toFixed(0);
var Foo;
(function (Foo) {
Foo["A"] = `${BAR}`;
Foo["B"] = "2" + BAR;
Foo["C"] = (`${BAR}`);
Foo["D"] = (`${BAR}}`);
Foo["E"] = `${BAR}`;
})(Foo || (Foo = {}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//// [tests/cases/compiler/computedEnumMemberSyntacticallyString2.ts] ////

//// [foo.ts]
import { BAR } from './bar';
enum Foo { A = `${BAR}` }

//// [bar.ts]
export const BAR = 'bar';

//// [bar.js]
export const BAR = 'bar';
//// [foo.js]
import { BAR } from './bar';
var Foo;
(function (Foo) {
Foo["A"] = "bar";
})(Foo || (Foo = {}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//// [tests/cases/compiler/computedEnumMemberSyntacticallyString2.ts] ////

//// [foo.ts]
import { BAR } from './bar';
enum Foo { A = `${BAR}` }

//// [bar.ts]
export const BAR = 'bar';

//// [bar.js]
export const BAR = 'bar';
//// [foo.js]
import { BAR } from './bar';
var Foo;
(function (Foo) {
Foo["A"] = "bar";
})(Foo || (Foo = {}));

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions tests/cases/compiler/computedEnumMemberSyntacticallyString.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @isolatedModules: true,false
// @noTypesAndSymbols: true
// @target: esnext

const BAR = 2..toFixed(0);

enum Foo {
A = `${BAR}`,
B = "2" + BAR,
C = (`${BAR}`),
D = (`${BAR}}`) as string,
E = `${BAR}`!,
}
10 changes: 10 additions & 0 deletions tests/cases/compiler/computedEnumMemberSyntacticallyString2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @isolatedModules: true,false
// @noTypesAndSymbols: true
// @target: esnext

// @filename: ./foo.ts
import { BAR } from './bar';
enum Foo { A = `${BAR}` }

// @filename: ./bar.ts
export const BAR = 'bar';