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

返回联合类型引发TypeScript类型校验报错,如何解决?

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

这个问题是TypeScript里联合类型的常见场景——当你拿到一个可能是两种不同类型的值时,TypeScript没办法确定当前到底是哪一种,所以直接访问某一个类型独有的属性就会报错,就像你遇到的code属性不存在于IMakes的提示。

下面给你几种实用的解决办法:

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

这是最简单的方式,不需要额外写函数,直接检查目标属性是否存在,TypeScript会自动推断类型:

getCarMakes(2024).then(data => {
  if ('code' in data) {
    // 这里TypeScript明确知道data是IErrorResponse类型
    console.error(`请求失败:${data.code} - ${data.msg}`);
  } else {
    // 这里自动推断为IMakes类型
    console.log('可用车型品牌:', data.makes);
  }
});

2. 自定义类型谓词函数

如果需要更复杂的判断逻辑,或者想把类型检查逻辑复用,可以写一个自定义的类型守卫函数:

// 定义一个类型谓词,告诉TypeScript如果函数返回true,参数就是IErrorResponse
function isErrorResponse(res: IMakes | IErrorResponse): res is IErrorResponse {
  // 检查code属性是否存在且是数字类型(可选,更严谨)
  return typeof (res as IErrorResponse).code === 'number';
}

// 使用的时候
getCarMakes(2024).then(data => {
  if (isErrorResponse(data)) {
    console.error(`错误码:${data.code},消息:${data.msg}`);
  } else {
    console.log(data.makes);
  }
});

3. 进阶:改用区分联合类型(Discriminated Union)

如果API允许调整返回格式,或者返回结果里本来就有一个用来区分成功/失败的字段(比如type或status),推荐把接口改成区分联合类型,这是TypeScript处理这类场景最清晰的方式:

// 修改接口,添加一个共同的区分字段
interface IMakes {
  type: 'success'; // 成功响应的标识
  makes: string[];
}

interface IErrorResponse {
  type: 'error'; // 错误响应的标识
  code: number;
  msg: string;
}

// 调用时用switch判断类型
getCarMakes(2024).then(data => {
  switch (data.type) {
    case 'error':
      console.error(`请求出错:${data.code} - ${data.msg}`);
      break;
    case 'success':
      console.log('车型列表:', data.makes);
      break;
  }
});

这种方式下,TypeScript会根据type字段精准推断类型,完全不会有属性访问的报错,代码可读性也更高。

额外优化:统一函数返回值

另外注意你原来的函数里,catch块是直接throw new Error(error),这会让函数的返回值变成Promise<IMakes | IErrorResponse> | Promise<never>(因为抛出错误会终止Promise链)。如果想让函数始终返回Promise<IMakes | IErrorResponse>,可以把错误转换成IErrorResponse对象返回:

export const getCarMakes = (year: number): Promise<IMakes | IErrorResponse> => {
  return fetch('url', { method: 'GET' })
    .then((res: Response) => res.json())
    .then((data: IMakes | IErrorResponse) => data)
    .catch((error: any) => { 
      // 将捕获的错误转换成IErrorResponse格式返回
      return { code: 500, msg: error.message || '请求失败' } as IErrorResponse; 
    });
};

这样调用方只需要处理返回的联合类型,不用额外处理Promise的reject状态,更符合你最初定义的函数返回类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:39:05