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

如何处理Typescript联合类型中非共有属性的访问与类型校验问题?

知识点遗漏说明

你遗漏的是 TypeScript 的类型收窄(Narrowing) 相关规则:

  • 联合类型变量在完成类型收窄前,仅允许访问所有联合成员共有的属性,GeneralAPIError 和 Foo 只有 status 是共有属性,直接访问 whatever 必然触发类型报错
  • 默认情况下 TypeScript 不会将 hasOwnProperty 调用的返回值作为类型收窄的依据,因为该方法可被重写,可靠性不足

返回类型最优声明方案

推荐使用 可辨识联合(Discriminated Union) 实现,你现有两个类型都自带 status 字段,刚好可以作为辨识标记,只需要调整成功类型的 status 为字面量类型即可,通用错误类型可以完全复用在所有同类接口函数中:

type GeneralAPIError = {
  status: "error";
  message: string;
};

// 仅需把原Foo的status从string改为字面量类型"success"
type Foo = {
  status: "success";
  whatever: string;
}

// 函数返回值类型不需要额外修改
function wat(): Foo | GeneralAPIError {
  return Math.random() > .5 ? {
      status: "error",
      message: "noooo"
  } : {
      status: "success",
      whatever: "yayyy"
  };
}

使用时直接判断 status 即可自动完成类型收窄,不需要任何类型断言:

const eh = wat();

if (eh.status === "success") {
  // TS自动将eh收窄为Foo类型,直接访问属性无报错
  console.log(eh.whatever);
} else {
  // TS自动将eh收窄为GeneralAPIError类型
  console.log(eh.message);
}

如果你坚持用「判断属性是否存在」的逻辑

可以自行封装一个通用的类型守卫函数,所有同类场景都可以复用,不需要写断言:

// 通用属性存在判断类型守卫
function hasProperty<T extends object, K extends PropertyKey>(obj: T, key: K): obj is T & Record<K, unknown> {
  return key in obj;
}

// 使用示例
const eh = wat();
if (hasProperty(eh, "whatever")) {
  console.log(eh.whatever);
} else {
  console.log(eh);
}

注意:eh.whatever || eh 这种写法无法直接通过类型校验,这是 TypeScript 类型安全的强制要求,你可以改用可选链写法 eh?.whatever || eh 规避报错,但此时 whatever 的类型会被推断为 string | undefined,仍需额外处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 00:06:07