javascript - 如何利用有区别的联合来推断函数的返回类型

标签 javascript typescript class generics union

鉴于以下类型、接口(interface)和 getData 函数,我试图找到一种利用可区分联合的方法,以便 TS 编译器可以缩小 getData(source: DOSources) 的返回类型。到相关的DOTypes

// Expected behavior
const result = getData("dataObjectA");

// result.data should be a string but in this case the TS compiler will complain 
// that data does not have the toLowerCase() function
result.data.toLowerCase();
示例代码
interface DataObjectA {
  source: "dataObjectA";
  data: string;
}

interface DataObjectB {
  source: "dataObjectB";
  data: number;
}


type DOTypes = DataObjectA | DataObjectB
type DOSources = DOTypes["source"];

async function getData(source: DOSources) {
  const response = await fetch(`https://some-random-endpoint/`, {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  });

  switch (source) {
    case "dataObjectA":
      return await response.json() as DataObjectA;
    case "dataObjectB":
      return await response.json() as DataObjectB;
  }
}

最佳答案

您确实可以让编译器计算所需的返回类型 getData()作为 DOTypes 的函数有区别的联合和source的类型范围。您可以制作getData()一个 generic function其类型参数K extends DOSourcessource 的类型范围。例如:

async function getData<K extends DOSources>(source: K) {
  const response = await fetch(`https://some-random-endpoint/`, {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  });

  return await response.json() as Extract<DOTypes, { source: K }>
}
寻找DOTypes的成员与 K 相关的受歧视联合, 我们可以使用 the Extract utility type . Extract<DOTypes, {source: K}>选自DOTypes所有source 的工会成员属性的类型可分配给 K .
请注意,我们必须 assert该函数返回(一个Promise对应的)这个类型的值;编译器无法验证这一点。

让我们测试一下:
const resultA = await getData("dataObjectA"); // const result: DataObjectA
resultA.data.toLowerCase();

const resultB = await getData("dataObjectB"); // const result: DataObjectB
resultB.data.toFixed();
看起来不错。每个结果都缩小到预期的类型。您只会从 getData() 中得到一个联合。如果你把一个工会放在:
const resultAOrB = await getData(Math.random() < 0.5 ? "dataObjectA" : "dataObjectB");
// const resultAOrB: DataObjectA | DataObjectB
Playground link to code

关于javascript - 如何利用有区别的联合来推断函数的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68553075/

相关文章:

javascript - 根据对象数组中的第一个 "row"重命名 JSON 键

java - 如何将列表从类(class)传递到 Activity ?

c# - 命名空间和类同名?

node.js - Firebase部署找不到serviceAccountKey

typescript - 为什么 `type T1 = undefined & {}` 从不出现在 Typescript 中?

java - java中创建类什么时候有利

javascript - 如何在 ng-if 中添加自定义条件?

javascript - 为谷歌地图 API 中的现有标记添加信息窗口

javascript - 如何将一个下拉菜单中所选选项的属性添加到另一个下拉菜单?

javascript - 在 TypeScript 中将 IntelliSense 中的方法的别名显示为方法而不是属性