microsoft / tsyringe

Lightweight dependency injection container for JavaScript/TypeScript
MIT License
5.02k stars 168 forks source link

Basic register throws TypeInfo not known if constructor has parameters #223

Open brunocapdevila opened 1 year ago

brunocapdevila commented 1 year ago

Describe the bug While doing some unit test to evaluate the library I found that a simple class registration throws TypeInfo not Known only when it has construction parameters. It works when no construction parameters.

I must be missing something, but I already added

To Reproduce

By the way, I also tried having Toto constructor with only Bar parameter and still fails (in case primitive type needed to be handled differently)

import 'reflect-metadata';
import { container, injectable } from 'tsyringe';

beforeEach(() => {
  container.reset();
  container.clearInstances();
});

interface IToto {
  getName(): string;
}

@injectable()
class Bar {}

@injectable()
class Papa implements IToto {
  getName(): string {
    return 'papa';
  }
}

@injectable()
class Toto implements IToto {
  name: string = 'default';

  //constructor() {
  constructor(name: string, private value: Bar) {
    console.log(`TOTO instance created with name '${name}' and value '${value}'`);
  }

  public getName(): string {
    return this.name;
  }
}

describe('tsyringe bug ?', () => {
  test('constructor with parameters generates typeInfo not known', () => {
    container.registerInstance(Bar, new Bar());
    //container.register<IToto>('ITotot', { useToken: Toto });
    container.register(Toto, { useClass: Toto });
    container.register(Papa, { useClass: Papa });
    container.registerInstance(String, 'toto');

    const papa = container.resolve(Papa);
    const foo = container.resolve<Toto>(Toto);
  });
});

Expected behavior The instruction container.register(Toto, { useClass: Toto }); should be enough to create the related TypeInfo

Version: "tsyringe": "^4.7.0"

rsmrahul1 commented 11 months ago

@brunocapdevila Got any solution ?

rhenandias commented 6 months ago

Any solution?

epatrick commented 6 months ago

FWIW, I had this issue, and fixed with 2 changes:

chad-fossa commented 5 months ago

Given everything I've read about TSyringe, the solution is to inject each of your parameters. This sort of makes sense, given that in order for a class to be injectable, TSyringe needs to know how to fulfill each parameter in the constructor. In this case, you'd have to @inject('someThingForName') name: string etc for each of your parameters.

If you don't want to have the params be injected, you can instead use container.register('TotoClass', {useValue: new Toto(... inject yourself)}) or container.register('TotoClassType', {useValue: Toto})

leonardo-fernandes-atria commented 3 months ago

Terrible decision migrate the company api to use that DI library :\

smpark-dev commented 2 months ago

I am also experiencing the same issue.

When using tsx, this problem occurs: Example: "exec": "eslint && tsx watch --tsconfig ./tsconfig.json ./src/index.ts"

However, when running with node/esm, it works without any issues. Example: "exec": "eslint && pnpify node --import './loader.mjs' ./src/index.ts"

I am currently investigating the root cause.

DavidTheProgrammer commented 2 weeks ago

I am also experiencing the same issue.

When using tsx, this problem occurs: Example: "exec": "eslint && tsx watch --tsconfig ./tsconfig.json ./src/index.ts"

However, when running with node/esm, it works without any issues. Example: "exec": "eslint && pnpify node --import './loader.mjs' ./src/index.ts"

I am currently investigating the root cause.

Any luck?