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

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

Open
brunocapdevila opened this issue Mar 3, 2023 · 10 comments
Assignees

Comments

@brunocapdevila
Copy link

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"

@rsmrahul1
Copy link

@brunocapdevila Got any solution ?

@rhenandias
Copy link

Any solution?

@epatrick
Copy link

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

@chad-fossa
Copy link

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

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

@smpark-dev
Copy link

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
Copy link

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?

@cloudhx
Copy link

cloudhx commented Sep 17, 2024

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!

@thereis
Copy link

thereis commented Dec 10, 2024

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

@thereis
Copy link

thereis commented Dec 11, 2024

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.

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

No branches or pull requests