Cannot @Inject service into plain class
See original GitHub issueI am trying to use a utility service ( winston logger) in a plain TypeScript class. I can only get the instance of the service via Container.get(LoggerService). Using anything else like custom decorators @Logger() or @Inject(), constructor injection or property injection. All those ways lead to this.logger being undefined inside the Game class. Inside the Application, which is a service, the logger works perfectly fine. For minimal reproduction i have created this repo: https://github.com/drdreo/type-di-bug
Game instantiated like:
@Service()
export class Application {
constructor(
@Inject(ExpressServerImpl) private readonly server: IServer,
@Logger() private readonly logger: ILogger,
private readonly envService: EnvService
) { }
public readonly start = () => {
const port = this.envService.Port;
this.server.start(port);
this.logger.info(`Server listening at port ${port}`);
this.logger.info(`App running in [${this.envService.Env}] mode`);
const game = new Game(["foo"]);
};
}
import {ILogger} from "./interfaces/ILogger";
export class Game {
@Logger() private readonly logger: ILogger;
constructor(private players: any) {
// FAILS HERE, this.logger is undefined
this.logger.debug("Game has started");
}
}
How can i get the service injected into plain classes?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:3
- Comments:7
Top Results From Across the Web
How to inject service into class (not component) - Stack Overflow
Injections only works with classes that are instantiated by Angulars dependency injection (DI). You need to. add @Injectable() to MyClass and ...
Read more >Angular Dependency Injection: Complete Guide
The best way to understand dependency injection in Angular, is to take a plain Typescript class without any decorators applied to it, ...
Read more >Configuring dependency providers - Angular
The Creating and injecting services topic describes how to use classes as dependencies. ... If you specify the service class as the provider...
Read more >How to use dependency injection with strings and numbers in ...
You're probably familiar with dependency injection using classes, but what about using strings, numbers, booleans, or any other object?
Read more >Crux Dependency Injection - The Apache Software Foundation!
The IoC Container of Crux is the BeanProvider class. ... Due to restrictions imposed by runtimes, Crux cannot inject into private , protected...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

This seems to be the normal behaviour as far as runtime DI frameworks go.
In order for DI to work, it generally must follow a couple of guidelines:
The 3rd part is crucially important, as calling
newyourself will not inject dependencies. This can only be done with compile-time DI frameworks, such as Wire (Go) or Dagger (Java). Frameworks like this use code generation to achieve this.The other frameworks that use reflection work the same way as TypeDI by using runtime metadata. ASP.NET Core’s DI and Spring, and Angular. check out the Angular DI for an example of this:
https://github.com/angular/angular/blob/master/packages/core/test/di/reflective_injector_spec.ts
Notice how similar this is to TypeDI, although it is something that you do not actually notice when using Angular. In Angular, they have an entire framework dedicated to creating components. Their framework is what calls the
injector.get()method, while the end user only worries about creating and registering their components, not instantiating them.Angular does seem to have a way of registering classes without using annotations by using the static block. You can find examples of that here:
https://github.com/angular/angular/blob/master/packages/core/test/di/r3_injector_spec.ts
Long story short: You need to use
Container.getinstead of callingnew. You should not need to do this a lot sinceContainer.getwill inject nested services.This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.