【问题标题】:Typescript optionally extending interfaceTypescript 可选扩展接口
【发布时间】:2017-10-21 10:37:11
【问题描述】:

我有两个interfaces,其中一个扩展了另一个。但是,我希望能够扩展第一个 interface 并使其所有类型都是可选的。我不想在我的第二个interface 中重写第一个interface 的所有定义为可选(因为此时扩展的优势是什么?)或重新定义第一个interface,因为它是正在其他地方使用。

它的样子:

interface First {
  type1: string
  type2: string
}

// Seemingly pointless rewrite (why would I even need to extend?)
interface Second extends First {
  type1?: string
  type2?: string
  type3: string
  type4: string
}

// What I imagine the extending should be (but doesn't work)
interface Second extends First? {
  type3: string
  type4: string
}

我做了我的研究,发现this question 回答了非常相似的问题,但是自从这个问题被触及以来已经有一年了,我认为我的问题并不完全相同,因为我想让整个 扩展interface 可选,不只是其中的几个类型。

有没有什么办法可以在 Typescript 中做到这一点,还是我只需要把它吸起来然后花很长的时间interface


更新(解释我为什么想要这项工作):

我正在编写一个 React Web 应用程序,并且有一个组件可以显示我的数据库中的一个实体,这种方式允许用户编辑该实体的任何值。我希望我的 React 组件能够处理用户正在创建新实体的情况,以及用户正在编辑现有实体的情况。

为了与上面的示例保持一致,假设我的数据库实体的值由 First interface 复制,并且 React 组件使用存在于 Second 中的两个传递的道具强>interface。 React 组件将始终Second 中具有两个值,但不一定具有 First 中的值。

在用户创建新实体的情况下,我想只使用 Second 的值来构造 React 组件,而不必为 中的所有内容指定 null 值>首先。在用户编辑现有实体的情况下,我会传递 FirstSecond 的所有内容。

在这两种情况下,它都是相同的 UI,但使用一组不同的值构造。

【问题讨论】:

  • 你的情况是什么。更新帖子将帮助您

标签: javascript typescript interface


【解决方案1】:

您可以使用Partial 类型对接口执行此操作。

interface First {
    type1: string;
    type2: string;
}

interface Second extends Partial<First> {
    type3: string;
    type4: string;
}

【讨论】:

  • 这个答案从 TypeScript 2.2 版开始工作
【解决方案2】:

您还可以通过提供一个空接口来使所有部分成为可选:

export interface ISingleScope {
   scope: string;
}

export interface IMultiScope {
   scopes: string[];
   check?: boolean;
}

export interface IProvidedScope 
   extends Partial<ISingleScope>, Partial<IMultiScope> { 
}

但是,通常这需要对已使用的属性进行显式测试,因为在运行时这些信息都不存在。因此,如果您的对象带有名称 options,那么这就足够了:

if (options && options.scopes) {
   // access properly 'IMultiScope'
}

【讨论】:

    【解决方案3】:

    您可以在 Partial 类型上使用 type aliasesintersection

    type First = {
        type1: string;
        type2: string;
    }
    
    type Second = Partial<First> & {
        type3: string;
        type4: string;
    }
    

    【讨论】:

    • 你真是天赐之物。那是为我做的。在我一直使用DefiniteTyped 的所有时间里,我一无所知地没有注意到type 类型,并且在我的项目中到处都实现了interface
    • 它们在很多情况下几乎相同。请务必阅读 Interfaces vs. Type Aliases 以更好地了解它们的不同之处。
    • 现在我不那么年轻和天真了,我看到 interface Second extends Partial&lt;First&gt; 也可以正常工作(如下面 Dibyo 的回答所示)
    【解决方案4】:

    Extends in Typescript interface 表示第二个对象将继承第一个对象所具有的内容,如果第一个对象的属性是可选的,它们将不加更改地应用于第二个对象。您无法在 Typescript 中更改此行为。 你的问题的答案你不应该使用extends来解决你的问题。

    【讨论】:

    • 您对不同的方法有什么建议吗?我已经推断出extends 是错误的方法,这就是我在这里问这个问题的原因。
    • 实现所需的唯一方法是将第一个接口作为可选属性放在第二个对象中。不确定这是否适合您。
    • 但这会将 First 嵌套在可选属性中,而不是将所有 First 属性都放在 Second,对吧?如果是这样的话,它会起作用,但会有点尴尬。
    • 没错,但正如我已经告诉你的,要么将第一个接口的属性设为可选,要么在第二个单独重新声明它们。
    猜你喜欢
    • 2020-10-30
    • 2020-06-09
    • 2016-07-06
    • 2020-04-09
    • 2018-06-20
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多