I would like to have a function that returns an object instance based on a given identifier (e.g. string or symbol). In code it would look maybe something like:
// define your services
type ServiceA = { foo: () => string };
const ServiceA = { foo: () => 'bar' };
type ServiceB = { bar: () => number };
const ServiceB = { bar: () => 1 };
// register your services with identifier
registry.register('serviceA', ServiceA);
registry.register('serviceB', ServiceB);
// get a service by its type identifier
// the important thing here: I want to know the type!
const serviceA: ServiceA = registry.get('serviceA');
serviceA.foo();
A further requirement: ServiceA
and ServiceB
do not share an interface or so, they can be totally different.
The challenge in the shown example is to know the exact type of the value returned by registry.get
.
I tried an naive approach like:
enum ServiceType {
A,
B
}
const getService = (type: ServiceType): ServiceA | ServiceB => {
switch (type) {
case ServiceType.A:
return ServiceA;
case ServiceType.B:
return ServiceB;
default:
throw new TypeError('Invalid type');
}
};
and also the same thing with if
but the compiler is not able to derive the concrete type of the returned value, when I execute const x = getService(ServiceType.A);
the type of x is ServiceA | ServiceB
, what I would like to see is ServiceA
.
Is there any way to do something like this? If not, what is the reason for that from a compiler point of view?