0

Normally we can use Class recursively in TypeScript in following ways:

class A {
  b: B;
}

class B {
  a: A;
}

But when we use it with decorator and metadata we will get a ReferenceError like this:

ReferenceError: Cannot access 'B' before initialization

Here is a simple reproduction code.

// test.ts
const decorator = (target: any, property: any) => {};

class A {
  @decorator
  b: B;
}

class B {
  @decorator
  a: A;
}

// tsconfig.json
{
  "compilerOptions": {
    "target": "es2017",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Is there a good way to use decorator mode with metadata in TS?

BTW, it won't appear when the target under ES6, but we cannot use super in class constructor on those versions (refer: https://stackoverflow.com/a/51860850/7511849).

ps: I meet this problem when I use the NestJS framework recently, it uses decorator pattern and metadata a lot.

WangJie
  • 334
  • 1
  • 7
  • 1
    What's your use case for circular class references? What if you have these classes in separate files? – Jay McDoniel May 24 '21 at 15:13
  • @JayMcDoniel For abstract a Nested type like JSON. It's no error if putting these classes in separate files. Using module mechanisms seems a good way to avoid this error. Thanks a lot. – WangJie May 25 '21 at 08:23

1 Answers1

0

The error comes because these classes circularly reference each other, and typescript has a hard time with that while using decorators unless you're able to use some method to delay the process (some lazy load of sorts). Usually being able to do something like @Decorate(() => OtherClass) works well (TypeORM and Nest both have this idea), but to immediately get rid of the error you can at least move the classes to separate files. One class per file is usually a pretty good way to go

Jay McDoniel
  • 57,339
  • 7
  • 135
  • 147