Is there a way to implement a type-safe service registry in Typescript? I want a function that can return a specific type based on the argument provided.
For example:
get("a") should return an object of type ServiceA.
get("b") should return an object of type ServiceB.
I tried following the solution provided here: but I keep encountering typing errors.
I have simplified my issue and included the type errors I am facing:
console.log("Test get");
console.log("Get foo from AlertsService:", get('AlertsService').foo);
console.log("Get foo from AlertsService:", get('ModalService').foo);
console.log("Get foo from AlertsService:", get('ModalService').bar);
function get<T extends keyof ServiceMapping>(serviceType: T): ServiceMapping[T] {
const t: keyof ServiceMapping = serviceType;
switch (t) {
case 'AlertsService':
// TS2322: Type '{ type: "AlertsService"; foo: string; }' is not assignable to type 'ServiceMapping[T]'.
// Type '{ type: "AlertsService"; foo: string; }' is not assignable to type 'never'.
// The intersection 'AlertsService & ModalService' was reduced to 'never' because property 'type' has conflicting types in some constituents.
return {
type: 'AlertsService',
foo: 'testing'
};
case 'ModalService':
// TS2322: Type '{ type: "ModalService"; foo: string; bar: string; }' is not assignable to type 'ServiceMapping[T]'.
// Type '{ type: "ModalService"; foo: string; bar: string; }' is not assignable to type 'never'.
// The intersection 'AlertsService & ModalService' was reduced to 'never' because property 'type' has conflicting types in some constituents.
return {
type: 'ModalService',
foo: 'testing',
bar: 'bar test'
};
default:
throw new Error("nope");
}
}
export type ServiceMapping = {
AlertsService: AlertsService;
ModalService: ModalService;
}
export type AlertsService = {
type: 'AlertsService',
foo: string
}
export type ModalService = {
type: 'ModalService',
foo: string,
bar: string
}
I need the return type to be specific and not a union of different types.