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

通过方括号访问对象时联合类型的TypeScript类型推断问题

TypeScript联合类型动态访问的类型窄化问题解决方法

问题原因

TypeScript的控制流分析无法跟踪多次动态属性访问的关联关系。每次调用dummy.list[dummy.currentObjectId]时,TypeScript都会将其视为独立的联合类型访问操作,即便你已经通过type字段做了判断,后续再次访问该动态属性时,类型仍会回到联合类型。而先将结果赋值给变量后,TypeScript能跟踪变量的类型变化,从而正确完成类型窄化。

解决方案

1. 先将动态访问结果赋值给变量(最推荐)

这是最简单且安全的方式,把动态索引的结果存入变量后,TypeScript就能在控制流中正确窄化类型:

const currentObj = dummy.list[dummy.currentObjectId];
if (currentObj.type === types.BAR) {
  // 此处currentObj的类型被正确推断为TObject_BAR
  const assign = currentObj.type; // 类型为types.BAR
}

2. 优化类型定义,建立索引与类型的关联

如果希望TypeScript在编译期就识别currentObjectId与list键的对应关系,可以通过泛型约束强化类型定义:

// 让currentObjectId必须是list的键之一
type Example<T extends TPossibleObjectType> = {
  id: string;
  currentObjectId: keyof typeof T['list'];
  list: Record<keyof typeof T['list'], T>;
};

// 或者更精确地绑定对象id与类型的关系
type ExampleWithTypedIds<T extends TPossibleObjectType> = {
  id: string;
  currentObjectId: T['id'];
  list: Record<T['id'], T>;
};

// 使用satisfies让TypeScript自动推断类型
const dummy = {
  id: 'ex',
  currentObjectId: 'object_foo',
  list: {
    object_foo: { id: 'object_foo', type: types.FOO },
    object_bar: { id: 'object_bar', type: types.BAR },
  },
} satisfies ExampleWithTypedIds<TObject_FOO | TObject_BAR>;

注意:如果currentObjectId是运行时动态生成的值,这种方式仍需要配合变量赋值来做类型窄化。

3. 类型断言(仅在确定类型时使用)

如果能绝对保证当前currentObjectId对应的对象类型,可以使用类型断言,但这种方式会跳过TypeScript的类型检查,存在运行时风险:

const targetObj = dummy.list[dummy.currentObjectId] as TObject_BAR;
if (targetObj.type === types.BAR) {
  const assign = targetObj.type; // 类型为types.BAR
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:53:10