Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guidance on using InversifyJS with bundlers and build tools that don't support emitDecoratorMetadata #1493

Closed
zzzachzzz opened this issue Dec 20, 2022 · 7 comments

Comments

@zzzachzzz
Copy link

The readme states:

⚠️ Important! InversifyJS requires TypeScript >= 4.4 and the experimentalDecorators, emitDecoratorMetadata, types and lib compilation options in your tsconfig.json file.

It is a common scenario in web apps to use a bundler (Webpack, Rollup, ESbuild, etc.), either configured manually or through pre-configured dev environments (Vite, create-react-app), which may use a transpiler (Babel, SWC).

Most or all of these tools have limitations in what they can do with TypeScript.
ESbuild acknowledges it's lack of support for emitDecoratorMetadata:

The emitDecoratorMetadata TypeScript configuration option is not supported. This feature passes a JavaScript representation of the corresponding TypeScript type to the attached decorator function. Since esbuild does not replicate TypeScript's type system, it does not have enough information to implement this feature.

I know Babel is partially or fully capable of working around this limitation with various plugins.

The questions I hope to have answers to (preferably in the InversifyJS docs) are:

  1. What limitations are acknowledged for projects using build tools besides tsc?
  2. Do these limitations prevent the use of InversifyJS altogether, or just prevent the use of certain features? The Support for classes documentation does touch on this a bit.
@gabbanaesteban
Copy link

gabbanaesteban commented Feb 20, 2023

Can someone from the core team or maintainers answer this? Im interested too.
@remojansen

@PodaruDragos
Copy link
Member

I'm not sure what is to say here. inversify relies heavily on decorators with emitDecoratorMetadata.
We can investigate this, look at other packages that works with swc.
As far as I am aware there should not be a problem while using babel/webpack with a ts-loader.

From my personal experience I haven't used inversify with anything else than tsc, so I can't really offer a solution.
Maybe other guys from the core team can provide some feedback.

@gabbanaesteban
Copy link

@PodaruDragos what is odd to me is that it works with emitDecoratorMetadata set to false using tsc.
Also, it works using esbuild, which does not support emitDecoratorMetadata.

That's why we are asking what those limitations are, those features that won't work without emitDecoratorMetadata set to true?

@PodaruDragos
Copy link
Member

I will have to look into this, but @notaphplover can probably have a good answer for this.

@notaphplover
Copy link
Member

I will have to look into this, but @notaphplover can probably have a good answer for this.

I'll do my best @PodaruDragos. After having a look at the source code, this library only uses design:paramtypes metadata emited to decorate classes with the Injectable class decorator and propagates this metadata for the purpose of giving support to classes. This is, as @zzzachzzz suggested, the only feature you would be missing if you don't emit decorator metadata.

So, regarding the questions raised in the issue:

What limitations are acknowledged for projects using build tools besides tsc?

For build tools that don't support emitDecoratorMetadata? The container won't be able to take advantage of that metadata and you'll need to declare all your class constructor dependencies.

Do these limitations prevent the use of InversifyJS altogether, or just prevent the use of certain features? The Support for classes documentation does touch on this a bit.

Only https://github.com/inversify/InversifyJS/blob/master/wiki/classes_as_id.md

Hope I answered to all your questions :)

@zzzachzzz
Copy link
Author

Thank you @notaphplover, I believe that does answer all my questions. It's been a little while since I looked at this project so let me see if I understand:

Without emitDecoratorMetadata, Inversify is not able to determine the type to inject, when relying on class metadata (i.e classes as id). Therefore, the use of a Symbol or string id along with @inject is necessary.

Example with emitDecoratorMetadata support:

private _katana: Katana;
public constructor(katana: Katana) {
    this._katana = katana;
}

Example without emitDecoratorMetadata support:

private _katana: Katana;
public constructor(@inject(TYPES.Katana) katana: Katana) {
    this._katana = katana;
}

Along with the difference in how the dependencies are bound to their identifiers in the DI container:

// with `emitDecoratorSupport`
container.bind<Katana>(Katana).to(Katana);
// versus without `emitDecoratorSupport`
container.bind<Katana>(TYPES.Katana).to(Katana);

Does that sound right? Feel free to close the issue.

@notaphplover
Copy link
Member

Exactly @zzzachzzz, that's it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants