I am trying to find an elegant way to inject an Interface into the tsyringe container based on a given value. (string/enum/Symbol)
This is how I would do it with a switch..case
clause:
interface IColor{
someMethod():void;
readonly someInfo:any;
}
class Blue implements IColor{
constructor() {
}
someMethod() {
console.log('I am blue');
}
}
class Red implements IColor{
constructor() {
}
someMethod() {
console.log('I am red');
}
}
@injectable()
class SurfaceService{
constructor(@inject('IColor')readonly color:IColor) {
}
}
// main
import {container} from "tsyringe";
const mainFunction = (someData:{colorinfo:string}) =>{
switch (someData.colorinfo){
case 'RED':
container.register("IColor", {useClass: Red});
break;
case 'Blue':
container.register("IColor", {useClass: Blue});
break;
}
const service = container.resolve(SurfaceService);
}
The problem with this approach is, that it is not very elegant and it requires to import all possible implementation even though, only one is needed at runtime.
Is there a better solution for this?
Here is a gist which was part of my research of DI solutions.
Apparently one has to use predicateawareclassfactory
. But I've found that a simpler version, that worked just fine ¯\_(ツ)_/¯
container.register(Tokens.logger, {
useFactory: () => {
return process.env.NODE_ENV === "production"
? container.resolve(PinoLogger)
: container.resolve(ConsoleLogger)
},
})