打字稿占位符通用

时间:2021-03-05 08:22:19

标签: typescript generics typescript-generics

假设给定数据

const dataA = {
  name: "John",
  age: 25,
  attributes: {specificA: "hello", specificA2: 14, nonspecific:"Well"},
}

const dataB = {
  name: "Lisa",
  age: 38,
  attributes: {specificB: "hello", someMoreSpecificStuff: true, nonspecific:"Hope this"},
}

const dataC = {
  name: "Peter",
  age: 60,
  attributes: {specificC: "hello", couldBeAnyName: "Oh My", nonspecific:"makes sense"},
}

我的一些组件只会访问一般信息(nameage
其他一些将只访问一般信息,但也会访问在键相同但值不同的属性中共享的一般信息 (attributes.nonspecific) 某些组件只能使用其中一种数据类型。

到目前为止我想到的是:

const dataA: MyDataType<A> = {
  name: "John",
  age: 25,
  attributes: {specificA: "hello", specificA2: 14, nonspecific:"Well"},
}

const dataB: MyDataType<B> = {
  name: "Lisa",
  age: 38,
  attributes: {specificB: "hello", someMoreSpecificStuff: true, nonspecific:"Hope this"},
}

const dataC:MyDataType<C> = {
  name: "Peter",
  age: 60,
  attributes: {couldBeAnything: "Oh My", nonspecific:"makes sense"},
}

type MyDataType<T extends A | B | C> = {
  name: string;
  age: number;
  attributes: T
}

type A = {
  specificA: string;
  specificA2: number;
  nonspecific: string;
}

type B = {
  specificB: string;
  someMoreSpecificStuff: true;
  nonspecific: string;
}

type C = {
  couldBeAnything: string;
  nonspecific: string;
}

这很好用,但如果我现在想要一个组件使用这些数据类型中的任何一种,我必须像这样输入:

interface ForMyGeneralComponent{
  data: MyDataType<A | B | C>
}

我想写的是

interface ForMyGeneralComponent{
      data: MyDataType<GenericType>
    }

并在某处声明 GenericTypeABC

为什么这么问?想象一下,这些属性可以由多达 30 种不同的类型组成。如果我必须在任何地方输入它们,这会大大降低可读性。我猜我也很懒?

Typescript playground

2 个答案:

答案 0 :(得分:2)

不确定,如果我理解你的用例。
也许您只想为所有属性引入一个新类型,例如

type MyAttributes = A | B | C;

type MyDataType<T extends MyAttributes> = {
  name: string;
  age: number;
  attributes: T
}

interface ForMyGeneralComponent{
  data: MyDataType<MyAttributes>
}

答案 1 :(得分:0)

<块引用>

所以我想我正在寻找的是构建一个适用于所有人的通用组件,它接受一个泛型,上面写着“我可以是任何子类,没关系”和打字稿确保我只使用属性在这些组件中是类型无关的

根据您对 other question 的评论,您肯定把这件事复杂化了!如果您有一些采用任何子类型的组件,那么您不需要通用或联合。您所需要的只是定义通用的部分。

type GeneralType = {
  name: string;
  age: number;
  attributes: {
    nonspecific: string;
  }
}

这不必成为泛型,但我们可以将其设为泛型,以便更轻松地创建特定版本。如果没有提供值,您可以为通用变量设置默认值。所以我们想要一个类型,它的默认状态是上面的 GeneralType,但也可以用来创建 A 数据、B 数据等。

我的建议是泛型变量应该只引用改变的属性。我不会在通用部分中包含 nonspecific: string,因为它始终存在。

这里我使用泛型 Extra 来指代除 attributes 之外的所有 nonspecific

type MyDataType<Extra extends {} = {}> = {
  name: string;
  age: number;
  attributes: Extra & {
    nonspecific: string;
  }
}

在一般情况下,只需省略 Extra,它将使用默认值,即一个空对象(没有额外的属性)。

interface ForMyGeneralComponent {
  data: MyDataType;
}
const dataGeneral: MyDataType = {
  name: "Peter",
  age: 60,
  attributes: {nonspecific:"makes sense"},
}

您的具体情况与之前的情况大致相同,const dataA: MyDataType<A> 等,但现在您不需要在 nonspecificAB

Typescript Playground Link