我有一個陣列as const:
// just a simple mock class
class Child { _ = "" }
const child = new Child();
const schema = [[child], child] as const; // readonly [readonly [Child], Child];
這個陣列代表一個型別的聯合,所以在這里,它代表一個陣列Child或另一個陣列Child(更深一層)。本質上,我想將型別schema轉換為(Child | Child[])[].
type T = UnwrapAsConstArray<readonly [readonly [Child], Child]> // => (child | Child[])[]
我正在為使這種轉變成為可能的邏輯而苦苦掙扎。這是我可憐的嘗試,效果不佳,正如您在底部看到的那樣。
一個游樂場,您可以在其中嘗試使用一些測驗用例和預期行為來制定解決方案。
請記住,我希望解決方案是遞回的并且適用于任何數量的嵌套。
類似的問題:從沒有 "as const" 的陣列創建型別元組。我需要我知道可能的“相反”。
uj5u.com熱心網友回復:
我的方法如下:
type UnwrapAsConstArray<T> =
T extends readonly any[] ? UnwrapAsConstArray<T[number]>[] :
{ -readonly [K in keyof T]: UnwrapAsConstArray<T[K]> }
DeepMutable<T>這與表單的普通型別非常相似
type DeepMutable<T> = { -readonly [K in keyof T]: DeepMutable<T[K]> }
這將使原語保持不變,并遞回地readonly從任何物件型別中剝離,將陣列保留為陣列,將元組保留為元組。唯一的區別是檢查readonly any[],我們顯式地獲取其元素型別的并集,對其執行T[number],并生成一個常規陣列。UnwrapAsConstArray
這通過了您示例中的所有測驗:
type UnwrappedSchema = UnwrapAsConstArray<typeof schema>;
// ^? type UnwrappedSchema = ({ _: string; } | { _: string; }[])[]
// not written as `(Child | Child[])[]`, but structrually identical
type Test01 = Assert<Equals<
UnwrappedSchema, (Child | Child[])[]>>; // okay
type Test02 = Assert<Equals<UnwrapAsConstArray<
readonly [readonly [1], 2]>, (2 | 1[])[] // okay
>>;
type Test03 = Assert<Equals<UnwrapAsConstArray<
readonly [1, readonly [2, 3], readonly [readonly [4, 5, 6]]]>,
(1 | (2 | 3)[] | (4 | 5 | 6)[][])[] // okay
>>;
type Test04 = Assert<Equals<UnwrapAsConstArray<
readonly []>, never[] // okay
>>;
type Test05 = Assert<Equals<UnwrapAsConstArray<
readonly [1]>, 1[] // okay
>>;
請注意,這將遞回地從您放入的任何物件型別中去除只讀Child,并且它不知道何時停止。任何無法在型別映射中幸存的東西都會很奇怪(函式型別將變為 just {})。如果您需要針對這些情況進行調整,則必須添加邏輯來執行此操作。
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/481041.html
標籤:打字稿
