扩展多个接口的更好方法

时间:2021-05-21 15:38:02

标签: typescript types interface

晚上好,

只是一个快速的,我不太擅长打字稿,但仍在寻找解决泛型的方法。 当然有更简洁或更简洁的方法来执行以下操作,在这种情况下最佳实践是什么?

export interface Fruit {
  colour: string;
  age: number;
  edible: boolean;
}

export interface A {
  Apple: Fruit[];
  Banana: Fruit[];
  Peach: Fruit[];
  Plum: Fruit[];
  Melon: Fruit[];
}

export interface B {
  diffApple: Fruit[];
  diffBanana: Fruit[];
  diffPeach: Fruit[];
  diffPlum: Fruit[];
  diffMelon: Fruit[];
}

export interface FruitIndex
  extends A, B, (etc)

我有这种情况,但是对于多个接口,它看起来真的很不整洁。 TIA

1 个答案:

答案 0 :(得分:1)

我希望“整洁”、“整洁”和“干净”在旁观者的眼中。您可以重构 AB 的定义以减少冗余。对于A

export type A = Record<"Apple" | "Banana" | "Peach" | "Plum" | "Melon", Fruit[]>;

这里我们使用 the Record<K, T> utility type,一个 mapped type,它为联合 T 中的每个键提供相同的属性值类型 K。您可以验证类型是否符合您的预期:

/* type A = {
    Apple: Fruit[];
    Banana: Fruit[];
    Peach: Fruit[];
    Plum: Fruit[];
    Melon: Fruit[];
} */

然后对于类型 B

export type B = { [K in keyof A as `diff${K}`]: A[K] }

这里我们使用 key remapping in mapped typestemplate literal types"diff" 前置到 A 的所有键,同时保持值相同。同样,您可以验证类型是否符合您的预期:

/* type B = {
    diffApple: Fruit[];
    diffBanana: Fruit[];
    diffPeach: Fruit[];
    diffPlum: Fruit[];
    diffMelon: Fruit[];
} */

这段代码比你原来的 AB 版本更简洁......但我不知道它是否更“整洁”。对于非专家可以理解的代码,有些话要说。不知道 { [K in keyof A as `diff${K}`]: A[K] } 的人可能不会将其描述为“干净”。


对于您的 FruitIndex,我看不出有什么方法可以使它更简洁;您需要在某处列出您希望扩展的所有父接口。您可以在此处的 extends 之后执行它,或者您制作一些其他结构,将其列出并从中计算 FruitIndex。无论哪种方式,您都会在某处再次输入 AB。所以我会保持原样,至少在这个例子中:

export interface FruitIndex extends A, B { }

Playground link to code