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

如何让TypeScript工具类型Required对接口嵌套成员生效?

问题本质

TypeScript 内置的Required<T>是浅层转换工具,原生实现仅会移除当前对象层级属性的?可选修饰符,不会递归处理属性值为对象的嵌套结构,因此嵌套层级的可选属性不会被标记为必填。
原生Required的实现源码如下,可以看到没有递归逻辑:

/**
 * Make all properties in T required
 */
type Required<T> = {
    [K in keyof T]-?: T[K];
};
解决方案

自定义递归的深度必填工具类型DeepRequired<T>,遍历属性时如果检测到属性值是对象类型,就递归对该属性值做必填转换,直到遍历到原始类型为止。

基础实现(适配普通对象场景)

type DeepRequired<T> = {
  [K in keyof T]-?: T[K] extends object ? DeepRequired<T[K]> : T[K]
}

兼容数组、函数的增强实现

如果你的类型中包含数组、函数这类特殊引用类型,基础实现会错误递归,可以加分支判断单独处理:

type DeepRequired<T> = 
  // 函数类型直接返回,不做递归
  T extends (...args: any[]) => any 
    ? T
    // 数组类型单独处理,递归转换数组元素的类型
    : T extends Array<infer Item>
    ? Array<DeepRequired<Item>>
    // 普通对象递归移除所有层级可选修饰符
    : T extends object
    ? { [K in keyof T]-?: DeepRequired<T[K]> }
    : T
效果验证

替换原代码中的Required<Camera>为DeepRequired<Camera>后,TypeScript会校验所有嵌套层级的必填属性:

interface Camera {
    id? :string;
    name? : {
        firstName?:string;
        secondName? :string
    };
    site? :string
}

// 以下代码会触发类型错误:name属性缺少必填的firstName、secondName
const badCamera :DeepRequired<Camera> ={
    id :'1',
    name :{},
    site :'hello world'
}

// 所有层级属性补全后可正常通过校验
const validCamera :DeepRequired<Camera> ={
    id :'1',
    name :{
        firstName: "cam-01",
        secondName: "entrance"
    },
    site :'hello world'
}

内容的提问来源于stack exchange,提问作者Nyi Nyi Hmue Aung

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:36:17