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

TypeScript中无标识前缀的对象联合类型如何实现读取操作?

TypeScript中无标识对象联合类型的正确使用方式

问题场景

当使用无标识前缀的对象联合类型时,直接访问属性会触发TypeScript类型检查错误,比如:

function unionAsObject(a: { str: string } | { num: number }) {
   if (typeof a.str === 'string') { // 此处报错,TypeScript无法确定a是否包含str属性
   }
}

而基础类型联合、带标识的对象联合,TypeScript都能通过类型检查自动收窄类型:

基础类型联合示例

function unionAsType(a: string | number) {
   if (typeof a === 'string') {
      return a.indexOf('a'); // TypeScript识别此时a为string类型
   }
}

带标识的对象联合示例

function unionOfObjectsWithKeys(a: { type: 'str', str: string } | { type: 'num', num: number }) {
   if (a.type === 'str') {
      return a.str.indexOf('a'); // TypeScript通过type字段确定a的类型
   }
}

解决方案

1. 使用in操作符进行类型收窄

TypeScript支持通过in操作符检查对象是否包含目标属性,自动完成联合类型收窄:

function unionAsObject(a: { str: string } | { num: number }) {
   if ('str' in a) {
      // 此时TypeScript确定a是{ str: string }类型
      return a.str.indexOf('a');
   } else {
      // 自动推断a是{ num: number }类型
      return a.num.toString();
   }
}

2. 自定义类型守卫函数

如果需要更复杂的类型判断逻辑,可以自定义返回类型谓词的守卫函数:

type ObjectUnion = { str: string } | { num: number };

function isStrObj(obj: ObjectUnion): obj is { str: string } {
   return 'str' in obj && typeof obj.str === 'string';
}

function unionAsObject(a: ObjectUnion) {
   if (isStrObj(a)) {
      return a.str.indexOf('a');
   } else {
      return a.num.toString();
   }
}

3. 优化Extract用法(不推荐,仅作补充)

你之前使用Extract的方式可以简化,无需额外变量:

type ObjectUnion = { str: string } | { num: number };

function unionAsObject(a: ObjectUnion) {
   const strObj = a as Extract<ObjectUnion, { str: string }>;
   if (strObj.str !== undefined) {
      return strObj.str.indexOf('a');
   }
}

不过这种方式需要手动类型断言,不如前两种方法简洁直观。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:22:37