首页 > 解决方案 > 转换嵌套数组类型

问题描述

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

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

我设法使它适用于非嵌套数组类型和对象类型。我什至写了这个答案来转换对象类型的字段,除了嵌套数组的情况外,它工作得很好。

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

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]>};

但是由于类型别名不能循环引用自身,所以这是行不通的。有谁知道自动转换任意嵌套数组类型的解决方法?

标签: arraystypescript

解决方案


是的,这是一个已知的限制,但它特别有一个解决方法,Array<>比如interface. 请参阅DeepReadonly<T>来自@ahejlsberg拉取请求中引入条件类型的定义:

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>示例所示)。


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

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

希望有帮助;祝你好运!


推荐阅读