To better understand the concept, please refer to this code snippet:
type Type1 = { num1: number; str1: string };
type Type2 = { num2: number; str2: string };
type Type3 = { num3: number; str3: string };
type Type4 = { num4: number; str4: string };
enum MyEnum {
ONE,
TWO,
THREE,
FOUR,
}
type MyTypes<T> = T extends MyEnum.ONE
? Type1
: T extends MyEnum.TWO
? Type2
: T extends MyEnum.THREE
? Type3
: T extends MyEnum.FOUR
? Type4
: never;
const urls = {
[MyEnum.ONE]: 'http://one.com',
[MyEnum.TWO]: 'http://two.com',
[MyEnum.THREE]: 'http://three.com',
[MyEnum.FOUR]: 'http://four.com',
};
const fetchData = (_url: string): unknown => ({
// ...
});
export const myFun = <T extends MyEnum>(type: T) => {
const data = fetchData(urls[type]);
return { data: data as MyTypes<T> };
};
const one = myFun<MyEnum.ONE>(MyEnum.ONE);
const two = myFun<MyEnum.TWO>(MyEnum.TWO);
const three = myFun<MyEnum.THREE>(MyEnum.THREE);
const four = myFun<MyEnum.FOUR>(MyEnum.FOUR);
myFun()
accepts the type twice:
- As a generic type for static typing of the returned
data
. - As an argument used at runtime for selecting the correct
url
.
This method is effective, but I am seeking a way to simplify it by passing the type only once in either of these formats:
const a = myFun<MyEnum.ONE>(); // Option 1
const b = myFun(MyEnum.ONE); // Option 2
Is there a solution for this?
I have attempted:
- Option 1 (using generics only), but it lacks the capability to select the appropriate
url
dynamically. - Option 2 (using the argument only) like
, but then I struggle to assign the correct type to the returnedconst myFun = (type: MyEnum) => {...}
data
.
Note: I am open to any suggestions on simplifying this process. The current definition of MyTypes<T>
is cumbersome to me, so any alternative approach would be greatly appreciated.