reflect-metadata icon indicating copy to clipboard operation
reflect-metadata copied to clipboard

Reflect metadata circular dependency

Open SamJust opened this issue 4 years ago • 1 comments

I have a question regarding circular dependencies. I have an example here. The fact that confuses me, is that I only get one of the types undefined. When the built dist clearly shows, that both of the classes have this metadata set.

SamJust avatar Dec 04 '21 01:12 SamJust

This is a known limitation of the metadata format that Typescript emits. Newer metadata systems use a "resolver" pattern to get around this- for instance instead of using a SomeClass reference in the metadata, it will use () => SomeClass and expect the code retrieving the metadata to execute the function to obtain the class (constructor) reference.

The underlying reason is because in the case of a circular dependency, the inner required file is executed fully at the point in the outer file where it is imported. Code declared after the import occurs has not run yet. This is true of both CommonJS and ES modules, but in ES modules the name you give to an import is bound to the equivalent name which is exported from the imported file-- that is to say it is "live"-- so after both files are fully loaded the values are correct, this is why the "resolver" pattern works.

Getting around this can be painful / impossible without rearranging your code. Some libraries like TypeORM use the resolver pattern directly to allow for circular dependencies while still using the standard Typescript metadata emitting.

rezonant avatar Dec 04 '21 09:12 rezonant

As @rezonant mentioned, forward references require some type of deferral mechanism to avoid eager evaluation of an uninitialized reference. Unfortunately, we can't easily change the metadata format we emit in TypeScript since both C and () => C will appear to be functions when checked with typeof.

If we decide to support --emitDecoratorMetadata in TypeScript for the Stage 3 Decorators and Decorator Metadata proposals, we may end up completely redesigning the metadata format for that case.

For a few years now I have considered introducing a proposal for reified references that would be a broader solution to this issue. However, the complexity this might add to the language would require a large number of compelling use cases before it is likely to be considered.

rbuckton avatar Dec 13 '23 21:12 rbuckton