Skip to content

Decorated class gets name === "_a" when a #private field initializer references the class (regression in 7.0) #64494

Description

@bagbag

🔎 Search Terms

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.

⏯ Playground Link

TS 7 doesn't work on Playground

💻 Code

function dec(_target: unknown, _context: ClassDecoratorContext): void {}

@dec
class Foo {
  #self = Foo;
}

console.log(Foo.name);

No compiler options are needed: tsc with { "files": ["a.ts"] } (default target), then node a.js.

🙁 Actual behavior

Prints _a. 7.0 emits the class expression through a chained assignment to the temporary _a:

let Foo = (() => {
    var _a;
    let _classDecorators = [dec];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    var Foo = _a = class {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            Foo = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
        #self = Foo;
    };
    return Foo = _classThis;
})();

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScript

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions