I'am using typedi in a Node (express) project. I can't understand why, in my service class, the injection works fine as property injection but not as constructor injection.
This works:
@Service()
export default class AuthService {
@Inject("logger") private logger
@Inject("eventEmitter")
private eventEmitter!: EventEmitter;
constructor(
) {}
}
While this is not working:
@Service()
export default class AuthService {
@Inject("logger") private logger
@Inject("eventEmitter")
private eventEmitter!: EventEmitter;
constructor(
@Inject("logger") private logger,
@Inject("eventEmitter") private eventEmitter: EventEmitter
) {}
}
As an example, I use the logger and the emitter as follows:
public async SignUp(
userInputDTO: IUserInputDTO
): Promise<{ user: IUser; token: string }> {
try {
//some code
this.logger.silly("Hashing password");
const hashedPassword = await argon2.hash(userInputDTO.password, { salt });
this.logger.silly("Creating user db record");
this.eventEmitter.emit(userEvent.signUp);
//some code
return {
user: { },
token: "myToken",
};
} catch (e) {
this.logger.error(e);
throw e;
}
}
In the first case it works as expected , but in the second case, this.eventEmitter and this.logger are undefined.
As a side note:
- there aren't circular dependencies
- I imported 'reflect-metadata', in fact the decorators work fine if they are placed on properties and not in the constructor's parameters
- typedi, unless for this problem works fine. I can use Container#get , Container#set without any problem
CodePudding user response:
In the 2nd code snippet, you're already decorating AuthService
with @Service()
, which should be enough.
So change it to this and give it a try:
@Service()
export default class AuthService {
constructor(
private logger: YOU_NEED_A_TYPE_HERE,
private eventEmitter: EventEmitter
) {}
}
Just make sure to change YOU_NEED_A_TYPE_HERE
with the actual type of the logger, otherwise it won't work.
And then you should have your logger
and eventEmitter
references available:
public async SignUp(
userInputDTO: IUserInputDTO
): Promise<{ user: IUser; token: string }> {
try {
// logger and eventEmitter should have the right values
CodePudding user response:
It started working, but I'm not sure what caused it.
I worked on another machine with a newer node version (the example in this question was ran on node12 while it started working with node16).
I added a line in the
tsconfig.json
that was missing."emitDecoratorMetadata": true,
while "experimentalDecorators": true
was already there.
Maybe it's time to setup a small container to test it in different node versions.
As a side note, it seems that adding explicit type to the constructor parameter to inject is not strictly required (but anyway suggested). Also the @Inject
decorator seems also to be unnecessary as long as the class is already decorated with @Service