It is also possible to qualify a concrete type with a name to be able to register multiple implementations of some base class and let consumers choose which one they want.
Example:
import { injectable, qualify } from "@kayahr/cdi";
abstract class Logger {
public abstract log(message: string): void;
}
@injectable({ name: "null-logger" })
class NullLogger extends Logger {
public log(message: string): void {}
}
@injectable({ name: "console-logger" })
class ConsoleLogger extends Logger {
public log(message: string): void {
console.log(message);
}
}
@injectable({ inject: [ qualify(Logger, "console-logger") ]})
class ComponentA {
public constructor(logger: Logger) {
logger.log("Start");
}
}
@injectable({ inject: [ qualify(Logger, "null-logger") ]})
class ComponentB {
public constructor(logger: Logger) {
logger.log("Start");
}
}
In this example two Logger
singletons are registered under different names but under the same base type. ComponentA
and ComponentB
both depend on an instance of Logger
but because they use a qualified type as dependency ComponentA
gets the instance of ConsoleLogger
while ComponentB
get the instance of NullLogger
.
The advantage of using qualified types instead of just named dependencies is that TypeScript can check that the actually injected type is the type specified in the constructor signature.