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

TypeScript如何定义可自引用且兼容其他值的嵌套对象类型

TypeScript嵌套对象类型定义属性访问报错修复

问题场景

需要为任意层级的嵌套对象定义TypeScript类型,初始写法给变量赋值时校验正常,但访问对象属性时触发类型报错。
初始类型定义与报错代码:

type NestedObject = {
   [key: string]: NestedObject | string;
}

const obj: NestedObject = {
  a: '123',
  b: {
    b_a: {
      b_a_a: '456'
    },
    b_b: '789'
  }
};

function ABC(myNestedObject: NestedObject) {
    const nestedObject: NestedObject = {
      // 报错:Property 'fail' does not exist on type 'string | NestedObject'.
      'failProperty': myNestedObject.properties.fail 
    };
}

曾尝试通过条件类型判断值是否继承自string优化定义,但写法无法生效:

type NestedObject = {
  [K in NestedObject]: NestedObject[K] extends string ? string : NestedObject;
}

报错原因

  • 初始NestedObject使用字符串索引签名,TS会判定任意key对应的属性值类型都是NestedObject | string联合类型,静态检查阶段无法确定访问的属性值是字符串还是嵌套对象,直接在值上访问子属性时,TS会识别到string类型上不存在对象属性,抛出类型错误。
  • 自写的条件类型属于非法循环定义:[K in NestedObject]语法要求in后面跟键名的联合类型,NestedObject本身是对象结构类型,不是合法的键集合,因此写法直接失效。

修复方案

根据业务场景二选一即可:

  • 嵌套对象结构固定时:放弃通用索引签名,直接定义精确匹配结构的类型,TS可自动推导每个属性的准确类型,不会出现联合类型报错。
    // 匹配示例obj结构的精确类型
    type DefinedNestedObj = {
      a: string;
      b: {
        b_a: {
          b_a_a: string;
        };
        b_b: string;
      }
    }
    
  • 嵌套对象结构未知、需要兼容任意层级时:访问子属性前先做类型收窄,判断当前值不是字符串类型后再访问属性,符合TS类型检查规则。可以封装通用类型守卫简化判断:
    type NestedObject = {
      [key: string]: NestedObject | string;
    }
    
    // 类型守卫:判断值是否为嵌套对象
    function isNestedObject(val: unknown): val is NestedObject {
      return typeof val === 'object' && val !== null;
    }
    
    function ABC(myNestedObject: NestedObject) {
      const properties = myNestedObject.properties;
      const nestedObject: NestedObject = {
        // 收窄类型后安全访问属性
        'failProperty': isNestedObject(properties) ? properties.fail : ''
      };
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 07:21:38