You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

逻辑说明

  1. 用[K in keyof O]-?将所有可选属性转为必填属性(移除?修饰符)
  2. 辅助类型IsNotNullable用于识别被NotNullable包装的类型,提取内部的U
  3. 若属性是NotNullable<U>,直接返回U(确保不可为null)
  4. 若不是NotNullable类型,检查原属性是否为可选(即包含undefined):
    • 是可选属性:转为NonNullable<原类型> | null(必填可空)
    • 是必填属性:保留原类型不变

内容的提问来源于stack exchange,提问作者Tuan Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:05:42