在此TypeScript代码中泛型类型和参数都是必需的吗?

nlejzf6q  于 2022-12-24  发布在  TypeScript
关注(0)|答案(1)|浏览(161)

没有源代码很难解释这一点,所以请看下面的代码片段:

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()在这里接收相同的两次:

  • 作为泛型类型,静态用于确定返回的data的类型。
  • 作为一个参数,用于在运行时选择正确的url

注意这就像一个符咒。甚至写一些像myFun<MyEnum.ONE>(MyEnum.TWO)是不允许的,因为我不允许传递一个不同的类型的泛型和参数。返回的类型是正确的类型和myFun()的工作,因为我需要。

问题是什么?我发现它很难看,我想使用myFun()只传递一次类型,方法如下:

const a = myFun<MyEnum.ONE>();  // Option 1
const b = myFun(MyEnum.ONE);    // Option 2

有可能吗?
我试过:

  • 选项1(仅使用泛型),但在运行时无法选择正确的url
  • 选项2(只使用参数)作为const myFun = (type: MyEnum) => {...},但是我不能为返回的data分配正确的类型。
    • 注意**:任何其他简化的建议都是受欢迎的。例如,MyTypes<T>的定义看起来很难看,但我不知道其他的方法。
8qgya5xd

8qgya5xd1#

多亏了@Tobias S,我发现TypeScript在调用函数时不需要提供泛型,因为它是从参数中推导出来的。所以可以定义myFun()如下:

export const myFun = <T extends MyEnum>(type: T) => {
  const data = // ...
  return { data: data as MyTypes<T> };
};

但你可以把它当作

const { data } = myFun(MyEnum.ONE);

TypeScript将从泛型中推断data类型,泛型是从作为参数接收的值中推断出来的(因为它与泛型提供的相同)。

argument ------> generic --------> data
(provided)       (inferred)      (inferred)

相关问题