TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

ES `ClassDecoratorContext.name` has incorrect value with static `name`

Open miyaokamarina opened this issue 1 month ago • 1 comments

🔎 Search Terms

ClassDecoratorContext static name

🕗 Version & Regression Information

5.0.4-5.9.3

⏯ Playground Link

https://tsplay.dev/N7vAow

💻 Code

const decorate = (_: unknown, ctx: ClassDecoratorContext) => {
    console.log('decorate(%o)', ctx.name);
};

@decorate
class A {
    static get name() {
        return 2434;
    }
}

🙁 Actual behavior

ctx.name is 2434 (from A.name)

🙂 Expected behavior

ctx.name is 'A' (actual class name)

Additional information about the issue

The wrong value comes from the context initializer in the emitted code:

__esDecorate(
    null,
    (_classDescriptor = { value: _classThis }),
    _classDecorators,
    { kind: 'class', name: _classThis.name, metadata: _metadata },
    null,
    _classExtraInitializers,
);

The context name is initialized with _classThis.name (which triggers the getter) instead of the actual class name value (literal "A" in this case).

Possible Fix

Currently, the _classThis.name fragment comes from const classNameReference in transformClassLike in transformers/esDecorators.ts:

const classNameReference = factory.createPropertyAccessExpression(renamedClassThis, "name");

It should be adjusted to get an actual class name (either literal or computed), possibly like this:

const classNameReference = node.name ? factory.createStringLiteralFromNode(node.name) :
    node.emitNode?.assignedName ?? factory.createStringLiteral("")

miyaokamarina avatar Dec 09 '25 19:12 miyaokamarina

Hi @RyanCavanaugh !! Could I be assigned ??

The issue comes from using renamedClassThis.name, which invokes the user-defined getter. It should instead use the literal class name.

Happy to open a PR !!

sAchin-680 avatar Dec 11 '25 13:12 sAchin-680

Hello @RyanCavanaugh , I've submitted a fix for this issue! The fix uses the literal class name instead of accessing _classThis.name, exactly as suggested in the issue. Added a test case covering static name getter, static name property, and normal class scenarios.

Thanks @miyaokamarina for the detailed issue and suggested fix, it made implementing this straightforward!

AryanBagade avatar Dec 13 '25 09:12 AryanBagade