是的,这是一个已知的限制,但它专门为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> 示例所示)。
因此,对于您的情况,我们可以这样做:
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
希望有所帮助;祝你好运!