I have an existing typescript project using inversify. I have defined a logger in my TYPES at TYPES.ILoggger
and when I access the logger directly from my container it works:
import {ILogger} from "./interfaces/ILogger";
import {TYPES} from "./interfaces/TYPES";
import container from "./kernel/inversify.config";
const loggerFromTheContainer: ILogger = container.get<ILogger>(TYPES.ILogger);
loggerFromTheContainer.info("I WILL LOG"); // this works
So my setup should be fine.
I don't want to access the container directly but I want to use property injection. [InversifyJS' README provides an example:
If you prefer it you can use property injection instead of constructor injection so you don't have to declare the class constructor:
@injectable() class Ninja implements Warrior { @inject(TYPES.Weapon) private _katana: Weapon; @inject(TYPES.ThrowableWeapon) private _shuriken: ThrowableWeapon; public fight() { return this._katana.hit(); } public sneak() { return this._shuriken.throw(); } }
and I try to follow that one.
Yet when I try to inject the logger through property injection, I suddenly get undefined
as a logger and I don't know why:
@injectable()
class ShouldHaveLogger {
@inject(TYPES.ILogger) private logger: ILogger;
constructor() {
this.logger.info("Hello World"); // this.logger will remain undefined
}
}
new ShouldHaveLogger();
It will throw a generic
TypeError: Cannot read property 'info' of undefined
as this.logger
is not being injected. Yet why and how to fix it?
The normal behavior of property injection is to let inversify
create the instances for you. You are now describing a use-case, in which you create the instance of ShouldHaveLogger
yourself (or another library is creating it for you).
This is also pointed out by the docs
In order to do that, you will need inversify-inject-decorators, as then you can inject the logger e.g. via @lazyInject
.
You have to setup lazyInject using your container and your code should look like:
import {injectable} from "inversify";
import getDecorators from "inversify-inject-decorators";
import {ILogger} from "./interfaces/ILogger";
import {TYPES} from "./interfaces/TYPES";
import container from "./kernel/inversify.config";
const {lazyInject} = getDecorators(container);
@injectable()
class ShouldHaveLogger {
@lazyInject(TYPES.ILogger) private logger: ILogger;
constructor() {
this.logger.info("I am working now");
}
}
new ShouldHaveLogger();
Will print depending on you logger implementation:
2019-01-30T09:47:54.890Z - info: "I am working now"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With