InversifyJS: "Missing required @inject or @multiInject annotation" even though it's there

Hey, I have the problem that I can’t get the injects working. It always says Missing required @inject or @multiInject annotation. Event though I add this annotation it still complains (I don’t have a circular dependency either).

Expected Behavior

Injection should work.

Current Behavior

I’m trying to get inversify working together with the latest create-react-app. Unfortunately no inject is working like expected. I took a really small example to reproduce this issue:

Steps to Reproduce (for bugs)

  1. create-react-app test --typescript
  2. cd test
  3. yarn add inversify reflect-metadata
  4. update tsconfig.json:
{
  "compilerOptions": {
    "target": "es5",
    "allowJs": true,
    "skipLibCheck": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "lib": ["es6", "dom"],
    "types": ["reflect-metadata", "node"],
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": [
    "src"
  ]
}
  1. replace whole content of src/index.tsx:
import {Container, injectable, inject} from 'inversify';
import 'reflect-metadata';

let container: Container = new Container();

const KatanaType: symbol = Symbol();
const ShurikenType: symbol = Symbol();
const NinjaType: symbol = Symbol();

@injectable()
class Katana {
    public hit() {
        return 'cut!';
    }
}

@injectable()
class Shuriken {
    public throw() {
        return 'hit!';
    }
}

@injectable()
class Ninja {

    public constructor(
        @inject(KatanaType) private katana: Katana,
        @inject(ShurikenType) private shuriken: Shuriken,
    ) {
    }

    public fight() {
        return this.katana.hit();
    }

    public sneak() {
        return this.shuriken.throw();
    }

}

container.bind<Katana>(KatanaType).to(Katana).inSingletonScope();
container.bind<Shuriken>(ShurikenType).to(Shuriken).inSingletonScope();
container.bind<Ninja>(NinjaType).to(Ninja).inSingletonScope();

container.get(NinjaType);
  1. run yarn start
  2. See error "Error: Missing required @inject or @multiInject annotation in: argument 0 in class Ninja. ".

Environment

Node version: v10.11.0 create-react-app version: 2.1.1

package.json:

{
  "name": "test",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@types/jest": "23.3.9",
    "@types/node": "10.12.10",
    "@types/react": "16.7.7",
    "@types/react-dom": "16.0.10",
    "inversify": "^5.0.1",
    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "react-scripts": "2.1.1",
    "reflect-metadata": "^0.1.12",
    "typescript": "3.1.6"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

I’m not sure if I have a wrong configuration somewhere or if this is a problem in create-react-app. I appreciate your help 😃

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 18
  • Comments: 27

Most upvoted comments

Fixed the issue by adding more babel plugins into the test environment, my babel.config.js now looks like:

module.exports = {
  env: {
    test: {
      plugins: [
        'transform-require-context',
+        'babel-plugin-transform-typescript-metadata',
+        'babel-plugin-parameter-decorator',
      ],
    },
  },
};

Hope this helps.

@Roustalski try to remove constructor and use property injection. I create PR to your repo.

My problem was that I’ve needed to add emitDecoratorMetadata to my tsconfig.json

{
  "compilerOptions": {
    "emitDecoratorMetadata": true
  }
}

For those who want to use InversifyJS with Next.js - here is the configuration I had to adjust.

tsconfig.json (if you are using TypeScript)

Add the following properties to compilerOptions:

{
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "types": ["reflect-metadata"],
}

babel.config.js

Create Babel config file in project root directory and add this content:

module.exports = {
  presets: ['next/babel'],
  plugins: [
    'babel-plugin-transform-typescript-metadata',
    ['@babel/plugin-proposal-decorators', { legacy: true }],
  ],
}

Install the following NPM modules as dev dependencies:

  • babel-plugin-transform-typescript-metadata
  • @babel/plugin-proposal-decorators
  • @babel/core

This seems to happen when you have a circular dependency issue, i.e: A requires B, B in turn requires (not via DI, just via an import) A.

https://github.com/aackerman/circular-dependency-plugin can be a handy way of chasing it down.

This is still happening, any news on what might be the problem?

@csr632, thanks for your answer. I would like to continue using babel, as we have some plugins there to build our bundle. However, I tried to configure the babel plugin and I’m still having the runtime error:

Error: Missing required @inject or @multiInject annotation in: argument 0 in class Ninja.

Here I forked @Roustalski 's repo to configure babel plugin. I’m not sure if I’m missing something or it is just not working: https://github.com/albertocorrales/broken-inversify

if you using index.ts, and import multiple classes from it, get rid of it. helped me.

This is 9/10 times due to a circular dependency. In my case it was Service1 injecting Service2 in its constructor and Service2 injecting Service1 in its constructor.

What a poor error message though.

For those who want to use InversifyJS with Next.js - here is the configuration I had to adjust.

tsconfig.json (if you are using TypeScript)

Add the following properties to compilerOptions:

{
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "types": ["reflect-metadata"],
}

babel.config.js

Create Babel config file in project root directory and add this content:

module.exports = {
  presets: ['next/babel'],
  plugins: [
    'babel-plugin-transform-typescript-metadata',
    ['@babel/plugin-proposal-decorators', { legacy: true }],
  ],
}

Install the following NPM modules as dev dependencies:

  • babel-plugin-transform-typescript-metadata
  • @babel/plugin-proposal-decorators
  • @babel/core

This fixed it for me. Thanks @georgwittberger-the-nu-company

Could someone inject dependencies at the constructor of a Mobx store? because I could achieve it only with property injection. Ortherwise I also get the “Missing required @inject or @multiInject annotation”

if you using index.ts, and import multiple classes from it, get rid of it. helped me.

This solved the issue for me too, but I have no idea why…

I can confirm that issue, also that @projekt86 workaround works. Do you have any idea what is cause of this?