我有幾種由大量交叉型別組成的型別。我想將這些型別提取到它們最終編譯成的內容中。我相信這在選擇重構方式時會有所幫助。
一個例子。鑒于此設定:
type BigType = {
thing: string
}
type LargeType = {
blah: boolean
}
type HugeType = BigType & LargeType
我想要某種輸出方式:
type HugeType = {
thing: string
blah: boolean
}
這是一個小例子——實際上有更多的型別交叉在一起。理想情況下,我會輸出這些型別“樹”的葉子 - 最大的結果型別。
關于原因的更多資訊。我們有一些復制粘貼的代碼,復制了型別、視圖(React 組件)和業務邏輯(RxJS 流)。速度是必要的,因此整個檔案夾都被復制粘貼,代碼針對一組新的功能需求進行了調整。我們現在想減少這種重復。
我們在 RxJS 流和 React 組件樹之間將視圖模型編碼為 Typescript 型別。為了減少重復代碼,我們正在討論的一種方法是將這些視圖模型拉入一個類層次結構中,并在超類中共享公共資料點,改變業務邏輯和視圖端的型別。在這些替換模型到位后,下一步將是重構雙方以減少在相同型別上運行的公共代碼。
所以我想從相交型別構建這些型別(視圖模型),因為我認為在計算這些不同但非常相似的視圖模型之間共享多少時會很有用。歡迎對此方法提供反饋。
uj5u.com熱心網友回復:
如果您相交的型別只有命名成員(因此它們也不會充當函式型別或建構式型別),那么您可以通過映射型別獲得您正在尋找的行為,該映射型別遍歷一個型別的所有命名成員(甚至是交集型別)并根據規則為每個成員生成一個屬性。如果將映射型別設為標識映射,其中每個屬性都映射到自身:
type Id<T> = { [K in keyof T]: T[K] };
那么您可以將交叉型別轉換為等效的單物件型別:
type HugeType = Id<BigType & LargeType>;
/* type HugeType = {
thing: string;
blah: boolean;
} */
效果很好,但有時編譯器喜歡保留型別別名,如IdIntelliSense 快速資訊中的名稱。如果您將滑鼠懸停在上面HugeType并且它確實顯示給您Id<BigType & LargeType>,那將比僅顯示更糟BigType & LargeType>。
如果遇到這個問題,我知道告訴編譯器不要保留這些名稱的一種方法是使用條件型別推斷將型別“復制”到新的型別引數中,然后使用型別引數代替原始型別型別:
type HugeType = (BigType & LargeType) extends infer H ?
{ [K in keyof H]: H[K] } : never;
/* type HugeType = {
thing: string;
blah: boolean;
} */
它在做和以前一樣的事情;我們正在對 執行身份映射BigType & LargeType,但現在沒有Id涉及任何型別別名,因此它不能出現在 IntelliSense 中。
編輯:哦,我看到你在談論“樹”。如果您的意思是物件屬性本身具有您可能需要以這種方式合并的屬性,那么您可以像這樣使用遞回定義的標識映射型別(這里的條件型別推斷確實有幫助):
type IdRecursive<T> = { [K in keyof T]: IdRecursive<T[K]> } extends
infer I ? { [K in keyof I]: I[K] } : never
并測驗它:
type X = {
a: {
b: {
c: number
}
}
}
type Y = {
a: {
b: {
d: string
}
}
}
type XY = IdRecursive<X & Y>
/* type XY = {
a: {
b: {
c: number;
d: string;
};
};
} */
Playground 鏈接到代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/383513.html
上一篇:帶有生成的javascript檔案的Typescript范圍變數
下一篇:省略擴展特定型別的屬性
