【问题标题】:Typescript Generic Array of InterfacesTypescript 通用接口数组
【发布时间】:2022-01-21 16:19:08
【问题描述】:

我对 TypeScript 中更高级的泛型类型有疑问。

我想要做的是一个数据数组,其中data 本身由type 控制,例如:

[
 {
  type: "T1",
  content: number,
 },
 {
  type: "T2",
  values: {
   id: number,
   ...
  }
 }
]

在描述了可用的类型后,我有点被堆积如山:

enum DataType {
 T1 = "t1",
 T2 = "t2"
}

所以我猜结果一定是这样的:

interface DataGeneric<T> {
 [T extends DataType.T1]: { content: number },
 [T extends DataType.T2]: { values: { id: number, ... } },
} ???

interface Data<T extends DataType = any(?)> extends DataGeneric<T>{
 type: DataType,
 // and all the other fields are generic from T = DataType
}
const someData: Data[] | undefined = fetchData();

// suggesting that the `type` of element[1] is "t2"
// and VSCode suggestions works correctly too,
// consider that there is an object-field `values` with `id` key
someData[1].values.id 

提前致谢!

【问题讨论】:

  • 您是否考虑过区分联合而不是泛型?见typescriptlang.org/docs/handbook/…
  • 看起来你肯定想要一个有区别的联合而不是通用的,比如this。如果该代码满足您的需求,我可能会写一个答案。如果没有,请告诉我缺少什么。
  • @jcalz 是的,是的!非常感谢!

标签: typescript generics


【解决方案1】:

如果您要根据字符串或数字 literal 检查对象的 type 属性,以区分对象的其余部分保存的数据类型,那么您可能希望使用 discriminated union 而不是泛型。这基本上是一个union type,工会的成员有一个共同的判别键。在您的情况下,它可能如下所示:

enum DataType {
  T1 = "t1",
  T2 = "t2"
}

type Data =
  { type: DataType.T1, content: number } |
  { type: DataType.T2, values: { id: number } }

然后当你有一个Data 类型的值data 时,你可以检查它的type 属性并且编译器知道它应该将data 缩小到联合的右成员:

declare const someData: Data[] | undefined;

if (someData) {
  someData.forEach(data => {
    if (data.type === DataType.T1) {
      data.content.toFixed();
    } else {
      data.values.id.toFixed();
    }
  })
}

Playground link to code

【讨论】:

    猜你喜欢
    • 2018-03-21
    • 1970-01-01
    • 2020-07-07
    • 2020-06-09
    • 2020-04-09
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多