網站搜尋

如何透過擴展從 TypeScript 介面移除欄位


假設有一個我無法控制的介面:

interface Original {
  name: string;
  size: number;
  link: SomeType;
}

我想擴展這個介面,但實際上是要移除link,所以我得到一個新的介面,其效果是:

interface OriginalLite {
  name: string;
  size: number;
}

我該怎麼做這個?

答案#1

您可以使用映射類型和條件類型來實現這個功能。通常我們把您想做的稱為 Omit:

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

(對於 TS3.5 以上版本,Omit 工具類型已包含在標準庫中,因此你不再需要自己定義它)

所以 Omit<T, K> 基本上與 T 相同,但不包含 K 中的任何屬性。你可以這樣做來創建一個名為 OriginalLite 的新 interface,它只缺少 link:

interface OriginalLite extends Omit<Original, 'link'> {}

請注意,你並沒有 擴展 Original。那是因為在 TypeScript 中,「擴展」意味著使一個類型更具體(也就是所謂的「收窄」),但在你的情況下,你所做的是使它不那麼具體(也就是所謂的「放寬」)。所以這就是為什麼在那個定義中沒有出現 extends Original。我假設這對你來說是可以的。

讓我們來測試它:

declare const originalLite: OriginalLite;
originalLite.name; // string
originalLite.size; // number
originalLite.link; // error, property 'link' does not exist on type 'OriginalLite'

看起來不錯。

答案#2

範例:從一個類型中省略多個不需要的屬性,並新增自訂屬性。

type UnwantedKeys = "key1" | "key2"

interface MyNewType extends Omit<Original, <UnwantedKeys>> {
  newProp1: string
  newProp2: number
}

答案#3

補充一下:如果你沒有想要移除的鍵列表,但只有介面,你可以使用 keyof 來獲取鍵的列表並將它們省略。

範例:

interface RemoveThoseKeys {
  removeMe1: unknown
  removeMe2: unknown
}

interface AllKeys {
  keep1: unknown
  keep2: unknown
  removeMe1: unknown
  removeMe2: unknown
}

type KeysAfterRemoval = Omit<AllKeys, keyof RemoveThoseKeys>

如果你用類型 KeysAfterRemoval 實例化一個對象,並在你的 IDE 中觸發自動完成功能,你應該只會得到 keep1 和 keep2。