In my code, I have a registry object structured as {[key]: <T>()=>T}
. The values of T
can vary, allowing me to easily add more entries in the future. I also have a function that takes a registry key as a string input and is supposed to return a value of the corresponding generic type. However, I'm encountering an issue where it returns a union of all generic types from the functions in the registry.
To simplify this explanation, I hope a basic working example effectively conveys my intentions.
type valFn<T> = () => T
declare const stringFn: valFn<string>;
declare const numberFn: valFn<number>;
const registry = {
alpha: stringFn,
beta: numberFn,
// ... additional records can be easily added without having to modify the +registryEater+ function every time, with all records following the pattern +key: ValFn<Something>+
};
// CHANGES CAN BE MADE ONLY DOWN FROM HERE
type ReturnType<T> = T extends valFn<infer R> ? R : never
const registryEater = <T extends keyof typeof registry>(registryKey: T): ReturnType<typeof registry[T]> => {
const desiredFn = registry[registryKey];
const desiredValue = desiredFn();
// TS2322 error points out that +desiredValue+ is string | number, but I need it to match the specific type based on the actual value of +registryKey+
return desiredValue;
};
// CHANGES CAN BE MADE ONLY UP FROM HERE
const thisIsString = registryEater('alpha');
const thisIsNumber = registryEater('beta');
To resolve this issue, one approach is changing return desiredValue;
to
return desiredValue as ReturnType<typeof registry[T]>;
. But is there a cleaner solution available?