TypeScript工具类型实现:可选属性转必填可空,排除NotNullable类型
TypeScript工具类型实现:可选属性转必填可空(保留NotNullable约束)
需求说明
- 将对象的可选属性转换为必填但可空属性(即
T | null) - 对象原有的必填属性保持类型不变
- 若属性类型为
NotNullable<T>(即使是可选属性),转换后不可为null,仅保留T类型
示例
输入类型:
type A = { a: number; b?: NotNullable<boolean>; c?: boolean; };
调用OptionalToNullable<A>后预期输出:
type B = OptionalToNullable<A>; /* { a: number; b: boolean; // NotNullable<boolean> 转为必填的boolean,不可为null c: boolean | null; // 普通可选属性转为必填可空 } */
错误实现分析
你提供的实现逻辑分支顺序有误,无法正确识别NotNullable<T>包装的可选属性:
export type NotNullable<T> = T extends null ? never : T; export type OptionalToNullable<O> = { [K in keyof O]-?: NotNullable<O[K]> extends NotNullable<infer V> ? V : undefined extends O[K] ? NonNullable<O[K]> | null : O[K]; };
问题在于:NotNullable<O[K]> extends NotNullable<infer V>这个判断会匹配所有非null类型,导致后续的可选属性判断无法生效,无法区分普通可选类型和NotNullable包装的可选类型。
正确解决方案
调整判断逻辑顺序,优先识别NotNullable<T>类型,再处理普通可选属性:
export type NotNullable<T> = T extends null ? never : T; // 辅助类型:判断类型是否为NotNullable包装类型 type IsNotNullable<T> = T extends NotNullable<infer U> ? U : never; export type OptionalToNullable<O> = { [K in keyof O]-?: // 优先判断是否为NotNullable<U>类型,若是则返回U(不可为null) IsNotNullable<O[K]> extends infer U ? U extends never // 不是NotNullable类型,再判断是否为可选属性(原类型包含undefined) ? undefined extends O[K] ? NonNullable<O[K]> | null : O[K] : U : O[K]; };
验证示例
用上述代码测试原示例:
type A = { a: number; b?: NotNullable<boolean>; c?: boolean; }; type B = OptionalToNullable<A>; // 结果符合预期: // { // a: number; // b: boolean; // c: boolean | null; // }
逻辑说明
- 用
[K in keyof O]-?将所有可选属性转为必填属性(移除?修饰符) - 辅助类型
IsNotNullable用于识别被NotNullable包装的类型,提取内部的U - 若属性是
NotNullable<U>,直接返回U(确保不可为null) - 若不是
NotNullable类型,检查原属性是否为可选(即包含undefined):- 是可选属性:转为
NonNullable<原类型> | null(必填可空) - 是必填属性:保留原类型不变
- 是可选属性:转为
内容的提问来源于stack exchange,提问作者Tuan Nguyen
相关产品推荐
相关产品推荐

