Skip to content

ES2022 Class Decorators not working when Class has self-static member #52004

Closed
@vladimir-siv

Description

@vladimir-siv

Bug Report

Class decorators are not working properly when the class has a static field of the same type and is instantiating it statically. Seems like this only happens when targeting ES2022.

🔎 Search Terms

Various combinations of the below search strings. Haven't been able to find anything useful.
Been searching for several days now, these are just the most recent ones I could remember:

  • Typescript class decorator with static property not working
  • Typescript decorators: TypeError: undefined is not a constructor
  • Typescript decorators not working (with es2022)
  • Typescript decorator es2022
  • Angular custom decorators not working
  • Angular custom decorators with aot

🕗 Version & Regression Information

Regressed when tsconfig.compilerOptions.target is ES2022. Other ES versions that I tried seem to be working as expected.
Tried Nightly version in the playground, could still repro it (after I changed target to ES2022 in TSConfig).

⏯ Playground Link

Bug repro in Playground
You can try setting e.g. ES2021, and the code works, but not on ES2022.

💻 Code

src\index.ts:

function Message(ctor: Function)
{
    console.log(`Registring: "${ctor.name}"`);
}

@Message
class PingMessage
{
    public static Default: PingMessage = new PingMessage(); // [A]
    public constructor(public readonly Value: string = "Ping") { }
}

// PingMessage.Default = new PingMessage(); // [B]
console.log(PingMessage.Default.Value);

// Swapping instantiation from [A] to [B] renders this code working.
// Seems like constructor is not defined well while instantiating a static member within its own class.

package.json:

{
  "name": "decorator-test",
  "version": "1.0.0",
  "description": "Test App",
  "scripts": {
    "start": "(if exist dist rd /S /Q dist) >nul 2>nul && tsc && node ./dist/index.js"
  },
  "dependencies": {
    "tslib": "^2.4.1"
  },
  "devDependencies": {
    "typescript": "^4.9.4"
  }
}

tsconfig.json:

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist",
    "target": "ES2022",  // <----- !!!
    "module": "ES2022",
    "strict": true,
    "experimentalDecorators": true,
    "useDefineForClassFields": false,
    "lib": [
      "ES2022",
      "dom"
    ]
  },
  "files": [
    "src/index.ts"
  ]
}

🙁 Actual behavior

~\dist\index.js:13
static { this.Default = new PingMessage_1(); } // [A]
          ^

TypeError: undefined is not a constructor
 at Function.<static_initializer> (~\dist\index.js:13:29)
 at Object. (~\dist\index.js:12:19)
 at Module._compile (node:internal/modules/cjs/loader:1155:14)
 at Object.Module._extensions..js (node:internal/modules/cjs/loader:1209:10)
 at Module.load (node:internal/modules/cjs/loader:1033:32)
 at Function.Module._load (node:internal/modules/cjs/loader:868:12)
 at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
 at node:internal/main/run_main_module:22:47

🙂 Expected behavior

Console.logs:

Registring: "PingMessage"
Ping

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions