TypeScript 复制现有接口,但更改一个属性的类型

dan*_*y74 7 typescript

我有这个界面:

interface IInternalListener {
  element: HTMLElement,
  id: string,
  type: string,
  listener: EventListenerOrEventListenerObject,
  useCapture: boolean
}
Run Code Online (Sandbox Code Playgroud)

我也想使用这个界面:

interface IListener {
  element: HTMLElement,
  id: string | number,
  type: string,
  listener: EventListenerOrEventListenerObject,
  useCapture: boolean
}
Run Code Online (Sandbox Code Playgroud)

唯一的区别是 的类型id。我想采用 DRY(不要重复自己)。

如何在不复制粘贴的情况下创建它。映射类型似乎是可行的方法,但在这个答案中,他们映射了所有道具 - Typescript: how do you create a Copy of a type but change the property typeing

我只想改变一个道具。我怎样才能做到这一点?我不必使用映射类型,任何可行的解决方案都是公平的。

Jar*_*ith 15

有几种方法可以做到这一点。

方式一

将公共逻辑提取到其他两个扩展的第三个接口中:

interface IWhatever {
  element: HTMLElement,
  type: string,
  listener: EventListenerOrEventListenerObject,
  useCapture: boolean
}

interface IListener extends IWhatever {
  id: string
}

interface IInternalListener extends IWhatever {
  id: string | number
}
Run Code Online (Sandbox Code Playgroud)

方式2

正如 Robby Cornelissen 在评论中指出的那样,您可以使用泛型:

interface IListener<T> {
  id: T
  element: HTMLElement,
  type: string,
  listener: EventListenerOrEventListenerObject,
  useCapture: boolean
}
Run Code Online (Sandbox Code Playgroud)

方式3

假设您不拥有 IListener 接口并且无法更改它,但您希望将其大部分内容重用于其他接口:

interface IInternalListener extends Omit<IListener, 'id'> {
  id: string | number
}
Run Code Online (Sandbox Code Playgroud)


0.s*_*.sh 5

您可以Omit一起使用扩展和实用程序类型。

例子

interface IInternalListener {
  element: HTMLElement,
  id: string,
  type: string,
  listener: EventListenerOrEventListenerObject,
  useCapture: boolean
}

interface IListener extends Omit<IInternalListener, 'id'> {
    id: string | number
}
Run Code Online (Sandbox Code Playgroud)

基本上,我们将删除该id属性并将其添加回您需要的首选类型。