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

如何访问仅存在于联合返回类型之一的属性?

TypeScript联合类型访问属性报错的解决方法

问题场景

调用函数返回联合类型:

const accountDetails: IAccount | ISmallError = getAccount()

尝试直接访问属性时触发编译错误:

if (accountDetails.error) return response.json({ error: error.error });

错误提示:

Property 'error' does not exist on type 'IAccount | ISmallError'.
  Property 'error' does not exist on type 'IAccount'.ts(2339)

你当前的解决方案是使用类型断言:

const err = accountDetails as ISmallError;
if (err.error) return response.json({ accountDetails: "No account found" });

方案评价与优化

你现在用的类型断言不是最优方案,因为它跳过了TypeScript的类型检查:如果accountDetails实际是IAccount类型,断言后访问err.error会得到undefined,存在运行时风险。

推荐以下更安全、符合TypeScript设计理念的解决方式:

1. 使用in操作符做类型守卫

这是最简单的方式,通过检查属性是否存在来缩小类型范围:

if ('error' in accountDetails) {
  // 此处TypeScript会自动推断accountDetails为ISmallError类型
  return response.json({ error: accountDetails.error });
}
// 下方代码中,accountDetails会被自动推断为IAccount类型,可安全访问其属性

2. 自定义类型守卫函数

如果需要更复杂的类型判断逻辑,可以封装守卫函数:

function isSmallError(obj: IAccount | ISmallError): obj is ISmallError {
  return (obj as ISmallError).error !== undefined;
}

if (isSmallError(accountDetails)) {
  return response.json({ error: accountDetails.error });
}
// 后续代码自动推断accountDetails为IAccount类型

3. 定义区分式联合类型(Discriminated Union)

如果可以修改类型定义,给两个类型添加共同的区分字段,能让类型判断更清晰:

// 修改类型定义
interface IAccount {
  type: 'account';
  // IAccount原有属性...
}

interface ISmallError {
  type: 'error';
  error: string;
  // ISmallError原有属性...
}

// 判断逻辑
if (accountDetails.type === 'error') {
  return response.json({ error: accountDetails.error });
}
// 下方自动推断为IAccount类型

这些方案既能通过编译检查,又能保证运行时的类型安全,比直接断言更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:15:37