如何透過擴展從 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。
