Typescript可选择扩展接口

Lou*_*cin 7 javascript interface typescript

我有两个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
}
Run Code Online (Sandbox Code Playgroud)

我做了我的研究,确实找到了一个回答非常类似问题的问题,但是这个问题已被触及了一年,我认为我的问题并不完全相同,因为我想让整个扩展interface可选,而不仅仅是一些它的类型.

有没有办法在打字稿中做到这一点,或者我只是需要吸吮它并做一个长时间interface


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

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

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

在用户创建新实体的情况下,我想构造仅具有Second值的React组件,而不必nullFirst中指定所有内容的值.在用户编辑现有实体的情况下,我会传递FirstSecond中的所有内容.

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

Nit*_*mer 18

您可以在Partial类型上使用类型别名交集:

type First = {
    type1: string;
    type2: string;
}

type Second = Partial<First> & {
    type3: string;
    type4: string;
}
Run Code Online (Sandbox Code Playgroud)

  • 现在我不再那么年轻和天真了,我发现“接口 Second extends Partial&lt;First&gt;” 也同样有效(如下面 Dibyo 的回答所示) (4认同)

小智 18

有一个更好/更简单的方法。使用Omit您可以仅重新定义特定的命名属性。

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

interface Second extends Omit<First, "type1"> {
    type1?: string;
}
Run Code Online (Sandbox Code Playgroud)


小智 10

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

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

interface Second extends Partial<First> {
    type3: string;
    type4: string;
}
Run Code Online (Sandbox Code Playgroud)


Joe*_*use 6

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

export interface ISingleScope {
   scope: string;
}

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

export interface IProvidedScope 
   extends Partial<ISingleScope>, Partial<IMultiScope> { 
}
Run Code Online (Sandbox Code Playgroud)

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

if (options && options.scopes) {
   // access properly 'IMultiScope'
}
Run Code Online (Sandbox Code Playgroud)


sha*_*een 5

Partial很棒,但有时您想要选择想要设为可选的键,而不是将它们全部设为可选!

为此,请使用: type Optional<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>

来源:这个可选答案来自这个问题, 如果您需要嵌套可选,请转到链接的问题。