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

如何创建根据状态变化的TypeScript Fetch响应类型?

解决方案

1. 重构响应类型定义

首先修正响应类型的逻辑,明确区分失败和成功的结构,同时用泛型支持不同接口的data字段:

// 失败响应:status 不为 0,无 data 字段
type ApiErrorResponse = {
  status: Exclude<number, 0>;
  message: string;
};

// 成功响应基础结构,泛型 TData 用于指定不同接口的 data 类型
type ApiSuccessResponse<TData> = {
  status: 0;
  message: string;
  data: TData;
};

// 完整 API 响应:失败或成功的联合类型
type ApiResponse<TData = never> = ApiErrorResponse | ApiSuccessResponse<TData>;

2. 修正API请求函数

让API函数支持泛型,并且返回完整的响应数据(之前的代码只返回了status和message,漏掉了data):

const api = async <TData>(url: string): Promise<ApiResponse<TData>> => {
  const res = await fetch(url);
  const json = await res.json();
  return json as ApiResponse<TData>;
};

3. 定义各接口的Data类型

为不同接口的成功响应data单独定义类型,提升类型安全性:

// 登录接口成功返回的data类型
type LoginSuccessData = { roles: string[] };
// 创建文档接口成功返回的data类型
type CreateDocSuccessData = { documentId: string };

4. 在业务函数中安全访问响应数据

通过类型守卫判断响应状态,TypeScript会自动推断出对应状态下的结构,避免报错:

const login = async (): Promise<void> => {
  const res = await api<LoginSuccessData>("...");
  
  if (res.status === 0) {
    // 此时TypeScript知道res是成功响应,可安全访问data.roles
    console.log("%s", res.data.roles[0]);
  } else {
    // 处理失败场景
    console.error("登录失败:", res.message);
  }
};

const createDoc = async (): Promise<void> => {
  const res = await api<CreateDocSuccessData>("...");
  
  if (res.status === 0) {
    // 此时TypeScript知道res是成功响应,可安全访问data.documentId
    console.log("%s", res.data.documentId);
  } else {
    // 处理失败场景
    console.error("创建文档失败:", res.message);
  }
};

问题根源说明

  • 原类型定义中,第一个分支status: number会包含0,导致TypeScript无法区分成功/失败分支,类型守卫失效。
  • 原API函数只返回status和message,即使类型正确,运行时也会缺失data字段。
  • 通过泛型+类型守卫的组合,既保证了类型安全,又能适配不同接口的响应结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:17:05