typescript - 递归应用复杂的泛型类型

标签 typescript generics null mapped-types

感谢 an answer来自 Nit,我有一个通用类型 NullValuesToOptional生成类型,其中每个可为 null 的值变为可选:

type NullValuesToOptional<T> = Omit<T, NullableKeys<T>> & Partial<Pick<T, NullableKeys<T>>>;

type NullableKeys<T> = NonNullable<({
  [K in keyof T]: T[K] extends NonNull<T[K]> ? never : K
})[keyof T]>;

type NonNull<T> = T extends null ? never : T;

有用:
interface A {
  a: string
  b: string | null
}
type B = NullValuesToOptional<A>; // { a: string, b?: string | null }

现在我想做 NullValuesToOptional递归:
interface C {
  c: string
  d: A | null
  e: A[]
}
type D = NullValuesToOptional<C>;
// { c: string, d?: NullValuesToOptional<A> | null, e: NullValuesToOptional<A>[] }

是否可以?

最佳答案

更新:包括 TS 3.7 版本 + 数组类型

你的意思是这样的吗?

TS 3.7+(数组中的通用类型参数现在可以是 circular ):

type RecNullValuesToOptional<T> = T extends Array<any>
  ? Array<RecNullValuesToOptional<T[number]>>
  : T extends object
  ? NullValuesToOptional<{ [K in keyof T]: RecNullValuesToOptional<T[K]> }>
  : T;

Playground

< TS 3.7(需要延迟 interface 的类型解析):
type RecNullValuesToOptional<T> = T extends Array<any>
  ? RecNullValuesToOptionalArray<T[number]>
  : T extends object
  ? NullValuesToOptional<{ [K in keyof T]: RecNullValuesToOptional<T[K]> }>
  : T;

interface RecNullValuesToOptionalArray<T>
  extends Array<RecNullValuesToOptional<T>> {}

Playground

测试类型:
interface A {
  a: string;
  b: string | null;
}

interface C {
  c: string;
  d: A | null;
  e: A[];
  f: number[] | null;
}

/*
type EFormatted  = {
    c: string;
    e: {
        a: string;
        b?: string | null | undefined;
    }[];
    d?: {
        a: string;
        b?: string | null | undefined;
    } | null | undefined;
    f?: number[] | null | undefined;
}

=> type EFormatted is the "flattened" version of 
type E and used for illustration purposes here;
both types E and EFormatted are equivalent, see also Playground
*/
type E = RecNullValuesToOptional<C>

用一些数据测试:
const e: E = {
  c: "foo",
  d: { a: "bar", b: "baz" },
  e: [{ a: "bar", b: "qux" }, { a: "quux" }]
};
const e2: E = {
  c: "foo",
  d: { a: "bar", b: "baz" },
  e: [{ b: "qux" }, { a: "quux" }]
}; // error, a missing (jep, that's OK)

关于typescript - 递归应用复杂的泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58411991/

相关文章:

Angular 库未构建为 es5 目标

javascript - 如何解决 ionic 2 中 self.context.anim is not a function 错误?

java - 是否需要重写以避免对 Java 泛型方法进行运行时类型检查?

ios - Swift 泛型中的文字

java - 使用对泛型对象的非类型化引用时,遍历成员类型化集合失败

mysql - 当只有空字符串通过 HTTP POST 来自客户端时,处理空值与数据库中的空字符串

java - 类和成员名称的通用 Java Logger 输出 null.null

mysql - 是否有理由不在mysql中使用<=>(空安全等于运算符)而不是=?

需要定义对象的任一属性的 typescript 类型 : how?

javascript - Angular 2 根据数字长度在数字之间放置空格