microsoft/tsyringe

Basic register throws TypeInfo not known if constructor has parameters

Opened this issue ยท 10 comments

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

  • reflect-metadata
  • decorators

To Reproduce

  • create the following jest unit test
  • launch
  • line const papa = container.resolve(Papa); --> works because Papa class has no parameters
  • line const foo = container.resolve<Toto>(Toto); -> fails with TypeInfo not know
  • replace Toto class constructor with an empty one -> it works

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"

@brunocapdevila Got any solution ?

Any solution?

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

  • added @injectable() in addition to being registered explicitly with container.register<myInterface>(token, { useClass: myClass }), and
  • tsconfig.json was missing "emitDecoratorMetadata": true

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})

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

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.

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?

Having the same issue running basic example:

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

@injectable()
class Foo {}

@injectable()
class Bar {
  constructor(public myFoo: Foo) {}
}

const myBar = container.resolve(Bar);

If class has no constructor parameters, it just works.

Anyone can shed some light on it? Thanks a lot!

facing the same issue with tsx, any luck @smpark-dev?

facing the same issue with tsx, any luck @smpark-dev?

I discovered that the reason is because of tsx uses esbuild under the hood and this makes the project to not support tsyringe and decorators.