You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
decorator class name _a, ES decorators private field class name, var Foo = _a = class, NamedEvaluation class name decorator, ClassDecoratorContext.name wrong, class .name regression 7.0, __esDecorate_classThis.name
🕗 Version & Regression Information
This changed between versions 6.0.3 and 7.0.1-rc. Also reproduces on 7.0.2 and 7.1.0-dev.20260926.1.
The anonymous class is the right-hand side of _a = …, so NamedEvaluation names it _a. Foo.name is "_a". So is ClassDecoratorContext.name, because the decorator context is built from _classThis.name. _a is never read afterwards.
🙂 Expected behavior
Prints Foo, as 6.0.3 does. 6.0.3's emit differs only in this line:
- var Foo = _a = class {+ var Foo = class {
The emitted class's name, and the decorator context's name, should be the declared class name.
Additional information about the issue
Reproducing needs both conditions below. With either one alone, 7.0 emits var Foo = class { and the name is correct:
an ES (standard) class decorator;
a #private field initializer that references the class.
A public field with the same self-reference keeps the name, and so does a #private field without it. target: esnext is unaffected, because decorators are not downleveled there.
Impact: code that uses Class.name or context.name sees _a, for example logger categories, diagnostics and DI registries.
Possible fixes: don't chain the unused temporary into the class expression, or emit __setFunctionName(_classThis, "Foo"), as is already done elsewhere.
🔎 Search Terms
decorator class name _a, ES decorators private field class name,
var Foo = _a = class, NamedEvaluation class name decorator,ClassDecoratorContext.namewrong, class.nameregression 7.0,__esDecorate_classThis.name🕗 Version & Regression Information
⏯ Playground Link
TS 7 doesn't work on Playground
💻 Code
No compiler options are needed:
tscwith{ "files": ["a.ts"] }(default target), thennode a.js.🙁 Actual behavior
Prints
_a. 7.0 emits the class expression through a chained assignment to the temporary_a:The anonymous class is the right-hand side of
_a = …, so NamedEvaluation names it_a.Foo.nameis"_a". So isClassDecoratorContext.name, because the decorator context is built from_classThis.name._ais never read afterwards.🙂 Expected behavior
Prints
Foo, as 6.0.3 does. 6.0.3's emit differs only in this line:The emitted class's name, and the decorator context's
name, should be the declared class name.Additional information about the issue
Reproducing needs both conditions below. With either one alone, 7.0 emits
var Foo = class {and the name is correct:#privatefield initializer that references the class.A public field with the same self-reference keeps the name, and so does a
#privatefield without it.target: esnextis unaffected, because decorators are not downleveled there.Impact: code that uses
Class.nameorcontext.namesees_a, for example logger categories, diagnostics and DI registries.Possible fixes: don't chain the unused temporary into the class expression, or emit
__setFunctionName(_classThis, "Foo"), as is already done elsewhere.Related, but not this bug: Incorrect transpilation of class name references in static contexts #54607, Bad esnext emit for static property that references another static property when the class has a decorator #44908, Decorators broken with private fields, generated code has syntax error #48515.