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

TypeScript如何定义任意深度且最终属性值为string/number的通用对象类型

错误原因

你定义的GenericObject接口使用了索引签名,其返回值是string | number | GenericObject | GenericObject[]联合类型。当你访问object.test2这类属性时,TypeScript无法确定该属性到底是基础值、嵌套对象还是对象数组,因此直接访问下层属性会抛出类型错误。

解决方案

方案1:使用satisfies操作符(推荐,适用于TypeScript 4.9及以上版本)

该方案既可以校验你定义的对象完全符合GenericObject的约束(保证末端值仅为string/number,支持任意层级嵌套),同时不会丢失对象本身的具体结构类型,访问嵌套属性不会触发类型错误。
代码示例:

interface GenericObject {
  [key: string]: string | number | GenericObject | GenericObject[];
}

// 用satisfies校验类型,不直接标注变量类型
const object = {
  test: 'test',
  testNum: 2,
  test2: {
    test: 'test'
  },
  test3: [
    {
      test: 'test'
    }
  ]
} satisfies GenericObject;

// 访问嵌套属性无报错
object.test2.test;
object.test3[0].test;

如果你的对象不符合GenericObject约束(比如末端值出现boolean等非法类型),TypeScript会在校验阶段直接抛出错误,符合你的需求。

方案2:使用类型收窄(适用于必须显式标注变量为GenericObject类型的场景)

如果业务要求你必须把变量的类型显式标注为GenericObject,可以在访问嵌套属性前先做类型判断,收窄属性类型后再访问:

interface GenericObject {
  [key: string]: string | number | GenericObject | GenericObject[];
}

const object: GenericObject = {
  test: 'test',
  testNum: 2,
  test2: {
    test: 'test'
  },
  test3: [
    {
      test: 'test'
    }
  ]
}

// 收窄test2类型为GenericObject后访问
if (typeof object.test2 !== 'string' && typeof object.test2 !== 'number' && !Array.isArray(object.test2)) {
  console.log(object.test2.test);
}

// 收窄test3为数组后再收窄子项类型
if (Array.isArray(object.test3)) {
  const item = object.test3[0];
  if (typeof item !== 'string' && typeof item !== 'number' && !Array.isArray(item)) {
    console.log(item.test);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:45:04