typescript - 從聯合類型中過濾掉具有已知鍵以外任意鍵的對象
給定像這樣的類型
type Test = { name: "a" } | { name: "b" } | { name: "c", other: 1 } | { name: "d", other: 2 }
我如何過濾出聯合類型中包含除「name」之外的鍵的類型。所以在這個例子中,結果類型將是 { name: "a" } | { name: "b" }。
這裡有一個 TS Playground:https://www.typescriptlang.org/play?#code/C4TwDgpgBAKhDOwoF4oG8oDsCGBbCAXFAETbFQC+UAPulnoSQEblW0Y75HEDGxANFAD2wABYQATkQCMlGnU6NiAEwHCxkogCZKAKF2hIUAGIBLADbBJEZXEQoo2TCH3mISAB5Ezl67YRIqBwM3HyCIuJSULJUAPSxUACiEhJCErpuSCDeFlYSNnaBCiEkZHLxJqaYEEA
答案#1
處理這類事情的一般方法是撰寫一個分配條件型別,將聯合輸入型別拆分成其各個成員,然後單獨保留或丟棄每個成員,之後再將它們重新合併成另一個聯合型別。這裡有一個可能的做法:
type Filter<T> = T extends unknown ?
Exclude<keyof T, "name"> extends never ? T : never
: never
所以 T extends unknown ? ⋯ : never 在泛型類型參數 T 上會分配到聯合類型。我使用的特定篩選器是 Exclude<keyof T, "name"> extends never ? T : never。Exclude<X, Y> 工具類型會移除與 Y 匹配的 X 的聯合成員,因此 Exclude<keyof T, "name"> 是 T 中不是 name 的鍵的聯合。如果該聯合為空(也就是不可能的 never 類型),那麼我們希望保留 T;否則我們就丟棄它。
好,我們來測試看看:
type Test = { name: "a" } | { name: "b" } |
{ name: "c", other: 1 } | { name: "d", other: 2 }
type FilteredTest = Filter<Test>;
/* type FilteredTest = { name: "a"; } | { name: "b"; } */
let x: FilteredTest = { name: "c", other: 1 } // Error
let y: FilteredTest = { name: "a" } // Fine
看起來不錯!
程式碼的 Playground 連結
