【问题标题】:"Overriding" TypeScript interfaces for extra specificity“覆盖” TypeScript 接口以获得额外的特异性
【发布时间】:2021-04-22 16:03:52
【问题描述】:

我觉得有一种简单的方法可以做到这一点,我可能只是想念。但基本上,给定这样的接口:

interface Order {
  type: string;
  additionalDetails: { [detail: string]: any };
}

我想覆盖/继承这个基接口的类型,但是有没有办法让任何这样做的接口 Order 只具有这两个属性?

// valid
interface Burger extends Order {
  type: 'cheeseburger';
  additionalDetails: {
    ketchup: boolean;
    cheese: boolean;
    mayo: boolean;
  };
}

// invalid
interface Dessert extends Order {
  type: 'icecream';
  additionalDetails: {
    cone?: boolean;
    waffle?: boolean;
  };
  flavor: string;
}

// invalid
interface Fries extends Order {
  type: 'fries';
}

// invalid
interface FriedChicken extends Order {
  additionalDetails: boolean;
}

我不完全确定 extends 是否是正确的方法,但如果我执行FriedChicken 接口之类的操作,我发现它的实现至少会引发错误。我认为泛型可能与它有关,因为我想要任何泛型,例如它扩展或包含Order 的属性,但我不完全确定。

【问题讨论】:

  • 这显然不是 Typescript 的用途。 Order 接口没用,extends 目的被滥用。你想用它实现什么?
  • 我想我很清楚我想要实现什么,并且我已经确定扩展不是实现我的想法的方法。总而言之,我想要一种“扩展”接口的方法,即重用它,但能够通过覆盖某些属性类型来更具体地定义它。在我的示例中,Order 有点像模板;任何有效的接口以及“扩展”和“覆盖”它必须具有且仅具有扩展现有类型的 typeadditionalDetail 属性。

标签: typescript typescript-generics


【解决方案1】:

这是我能得到的最接近的。

TS Playground

interface Order {
  // type: string; unfortunately this type had to change
  type: any;
  additionalDetails: { [detail: string]: any };
}

type Implements<T, U extends T> = {}

// valid
interface Burger extends Order {
  type: 'cheeseburger';
  additionalDetails: {
    ketchup: boolean;
    cheese: boolean;
    mayo: boolean;
  };
}

// invalid
interface Dessert extends Implements<Dessert, Order> {
  type: 'icecream';
  additionalDetails: {
    cone?: boolean;
    waffle?: boolean;
  };
  flavor: string;
}

// invalid
interface Fries extends Implements<Fries, Order> {
  type: 'fries';
}

// invalid
interface FriedChicken extends Implements<FriedChicken, Order>{
  additionalDetails: boolean;
}

有一个开放的 Github issue 似乎正是你想要的,基本上而不是有一个 interface extend 另一个 interface 你想让它们 implement 彼此。

此答案基于来自该问题的 comment,虽然它会在其他属性 (Desserts) 上引发错误,但不会在缺少属性 (Fries) 上引发错误。

Github 问题中有额外的 cmets 可能会为您提供您正在寻找的功能,不幸的是我无法弄清楚如何将它们组合用于您的用例。

【讨论】:

  • 我认为这正是我想要的,让界面能够implement 而不是extend。经过更多研究,我认为我实际上需要使用type 而不是interface,因为type 不允许在定义后添加更多属性。
  • 经过更多的实验和修改,我设法得到了我想要的一半。通过将interface Order 更改为type Order,然后将Implementation 更改为type Implements&lt;T extends Order&gt; = { },TS 可以确定扩展Order 的任何接口是否缺少任何属性。但是,我不能让它仅限于这两个属性,进一步的研究表明 TS 是为过度类型检查而构建的;它将检查扩展接口是否缺少属性,但不会检查它是否具有附加功能。我决定放弃我想做的事情。谢谢,:)
  • 是的,这听起来像是您所采取的方向与 TypeScript 的功能大相径庭。通常,在 TS 中有另一种方法可以完成类似的事情,而无需如此“hacky”。希望他们会添加类似implements 的内容,但我肯定会先尝试一些更简单的内容,看看它是否适合您:)。
猜你喜欢
  • 2020-03-06
  • 2018-08-18
  • 2017-02-16
  • 1970-01-01
  • 2012-06-30
  • 2019-08-17
  • 1970-01-01
  • 2021-06-11
  • 2017-05-08
相关资源
最近更新 更多