我有一个数组as const:
// just a simple mock class
class Child { _ = "" }
const child = new Child();
const schema = [[child], child] as const; // readonly [readonly [Child], Child];
Run Code Online (Sandbox Code Playgroud)
该数组表示类型的联合,因此在这里,它将表示一个数组Child或另一个数组Child(更深一层)。本质上,我想将 的类型转换schema为(Child | Child[])[].
type T = UnwrapAsConstArray<readonly [readonly [Child], Child]> // => (child | Child[])[]
Run Code Online (Sandbox Code Playgroud)
我正在努力寻找使这种转变成为可能的逻辑。这是我可怜的尝试,它的效果并不像你在底部看到的那么好。
一个可以尝试制定解决方案的游乐场,其中包含一些测试用例和预期行为。
请记住,我希望解决方案是递归的并且适用于任意数量的嵌套。
类似的问题:从不带 "as const" 的数组创建类型元组。我需要“相反”,我知道这是可能的。
我的方法如下:
type UnwrapAsConstArray<T> =
T extends readonly any[] ? UnwrapAsConstArray<T[number]>[] :
{ -readonly [K in keyof T]: UnwrapAsConstArray<T[K]> }
Run Code Online (Sandbox Code Playgroud)
这与表单DeepMutable<T>的普通类型非常相似
type DeepMutable<T> = { -readonly [K in keyof T]: DeepMutable<T[K]> }
Run Code Online (Sandbox Code Playgroud)
这将使基元保持不变,并递归地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
>>;
Run Code Online (Sandbox Code Playgroud)
请注意,这将递归地从Child您放入其中的任何对象类型中去除只读性,并且它不知道何时停止。任何不能在类型映射中生存的东西都会很奇怪(函数类型将变得只是{})。如果您需要针对这些情况进行调整,则必须添加逻辑来执行此操作。
| 归档时间: |
|
| 查看次数: |
613 次 |
| 最近记录: |