🔎 Search Terms
const enum, preserveConstEnums, use strict, directive prologue, non-simple parameter list, type erasure, invalid JavaScript emit
🕗 Version & Regression Information
- Reproduced with TypeScript 6.0.3.
- I could not find an existing issue for this specific interaction after searching for the terms above.
⏯ Playground Link
TypeScript Playground
💻 Code
function foo(a = 1) {
const enum E { x }
"use strict"
}
🙁 Actual behavior
With the default preserveConstEnums: false, TypeScript accepts the source and erases the const enum. The relevant emitted function is:
function foo(a = 1) {
"use strict";
}
The string is now the first statement in the function body and is reinterpreted as a Use Strict Directive. The emitted JavaScript is syntactically invalid because the function has a non-simple parameter list:
SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list
TypeScript does not report TS1347 on the source because the preceding enum declaration prevents the string from being recognized as part of the source directive prologue.
With preserveConstEnums: true, TypeScript emits the enum's runtime representation before the string. The string therefore remains an ordinary expression statement and the output is valid. The same accepted source consequently produces either valid or invalid JavaScript depending on whether the const enum is preserved.
🙂 Expected behavior
TypeScript should not emit syntactically invalid JavaScript from this accepted source. Erasing the const enum must preserve the boundary that keeps the following string expression from becoming a Use Strict Directive.
The exact emitted syntax and quote style are not important. For example, TypeScript could parenthesize the expression:
function foo(a = 1) {
("use strict");
}
Alternatively, it could emit an empty statement at the position of the erased declaration, preserving the directive-prologue boundary:
function foo(a = 1) {
;
"use strict";
}
Either output keeps the string as an ordinary expression statement and produces valid JavaScript.
Additional information about the issue
This is related to, but distinct from, #64033.
That issue discusses declarations such as type aliases that are always removed from JavaScript output. The TypeScript team response proposes treating those type-only declarations as transparent when determining the directive prologue.
A const enum is different because it is not unconditionally absent from the output: preserveConstEnums determines whether TypeScript erases it or emits a runtime enum. When it is preserved, it clearly precedes the string at runtime and prevents the string from being a directive. Erasing it should not silently change that source-level classification and, in this example, turn accepted TypeScript into JavaScript that cannot be parsed.
Even if always-erased type-only declarations are treated as transparent for #64033, the option-dependent behavior of const enum requires separate consideration.
🔎 Search Terms
const enum, preserveConstEnums, use strict, directive prologue, non-simple parameter list, type erasure, invalid JavaScript emit
🕗 Version & Regression Information
⏯ Playground Link
TypeScript Playground
💻 Code
🙁 Actual behavior
With the default
preserveConstEnums: false, TypeScript accepts the source and erases theconst enum. The relevant emitted function is:The string is now the first statement in the function body and is reinterpreted as a Use Strict Directive. The emitted JavaScript is syntactically invalid because the function has a non-simple parameter list:
TypeScript does not report TS1347 on the source because the preceding enum declaration prevents the string from being recognized as part of the source directive prologue.
With
preserveConstEnums: true, TypeScript emits the enum's runtime representation before the string. The string therefore remains an ordinary expression statement and the output is valid. The same accepted source consequently produces either valid or invalid JavaScript depending on whether theconst enumis preserved.🙂 Expected behavior
TypeScript should not emit syntactically invalid JavaScript from this accepted source. Erasing the
const enummust preserve the boundary that keeps the following string expression from becoming a Use Strict Directive.The exact emitted syntax and quote style are not important. For example, TypeScript could parenthesize the expression:
Alternatively, it could emit an empty statement at the position of the erased declaration, preserving the directive-prologue boundary:
Either output keeps the string as an ordinary expression statement and produces valid JavaScript.
Additional information about the issue
This is related to, but distinct from, #64033.
That issue discusses declarations such as type aliases that are always removed from JavaScript output. The TypeScript team response proposes treating those type-only declarations as transparent when determining the directive prologue.
A
const enumis different because it is not unconditionally absent from the output:preserveConstEnumsdetermines whether TypeScript erases it or emits a runtime enum. When it is preserved, it clearly precedes the string at runtime and prevents the string from being a directive. Erasing it should not silently change that source-level classification and, in this example, turn accepted TypeScript into JavaScript that cannot be parsed.Even if always-erased type-only declarations are treated as transparent for #64033, the option-dependent behavior of
const enumrequires separate consideration.