转换嵌套数组类型

时间:2018-05-03 17:18:47

标签: arrays typescript

我正在寻找一种可用于将任意深度的嵌套数组类型转换为另一种类型的类型。所以某些类型ConvertToBool<T>使得:

ConvertToBool<number[][][]> // should be boolean[][][]

我设法让这个适用于非嵌套数组类型和对象类型。我甚至写了this answer来转换对象类型的字段,除了嵌套数组的情况外,它的效果很好。

现在我想写一个这样的类型:

type Primitive = string | number | boolean | null | undefined;

type ConvertToBool<T> =
    T extends Primitive ? boolean :
    T extends (infer U)[] ? ConvertToBool<U>[] : // <-- Problem Line
    {[K in keyof T]: ConvertToBool<T[K]>};

但是由于类型别名不能循环引用自身,因此这不起作用。有没有人知道自动转换任意嵌套数组类型的类型的变通方法?

1 个答案:

答案 0 :(得分:2)

是的,这是一个已知的限制,但它特别针对像Array<> interface之类的任何内容进行解决。请参阅@ ahejlsberg pull request introducing conditional types DeepReadonly<T>type DeepReadonly<T> = T extends any[] ? DeepReadonlyArray<T[number]> : T extends object ? DeepReadonlyObject<T> : T; interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {} type DeepReadonlyObject<T> = { readonly [P in NonFunctionPropertyNames<T>]: DeepReadonly<T[P]>; }; 的定义:

DeepReadonly<T>

如文中所述:

  

与union和intersection类型类似,不允许条件类型以递归方式引用它们(但是,允许通过接口类型或对象文字类型进行间接引用 [强调我的] ,如上面的type Primitive = string | number | boolean | null | undefined; interface ConvertToBoolArray<T> extends Array<ConvertToBool<T>> {} type ConvertToBool<T> = T extends Primitive ? boolean : T extends (infer U)[] ? ConvertToBoolArray<U> : // okay now { [K in keyof T]: ConvertToBool<T[K]> }; 示例所示。

因此,对于您的情况,我们可以这样做:

declare const c: ConvertToBool<{ a: number, b: string[], c: { d: number }[] }>;
c.a // boolean
c.b[2] // boolean
c.c[3].d // boolean

type BoolBoolBool = ConvertToBool<number[][][]>
declare const bbb: BoolBoolBool;
bbb[0][1][2] === true; // okeydokey

让它看起来有效:

BoolBoolBool

这是有效的,但有一点需要注意boolean[][][]在检查时看起来不像ConvertToBoolArray<number[][]>;它是type IsSame<T extends V, U extends T, V=U> = true; // IsSame<T, U> only compiles if T extends U and U extends T: declare const sameWitness: IsSame<BoolBoolBool, boolean[][][]> // works ,但它们是等价的:

ifft

希望有所帮助;祝你好运!