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

如何创建带错误码的自定义类型响应,使调用者通过断言获取正确类型?

如何通过错误码断言获取API返回的对应类型

要实现调用者通过错误码断言获取对应正确类型,核心是用联合类型替代单一的Response类型,让TypeScript能根据code的字面量值自动缩小返回值的类型范围。以下是具体改造步骤:

1. 重构Response为联合类型

把原来通用的Response拆分为与每个错误码一一对应的类型,明确每个类型的data结构:

enum ErrorCode {
  OK = "OK",
  MAXIMUM_EXCEEDED = "MAXIMUM_EXCEEDED",
  UNKNOWN_ERROR = "UNKNOWN_ERROR",
}

type Person = {
  name: string;
  age: number;
};

type MaximumExceeded = {
  limit: number;
  inclusive: boolean;
};

// 每个错误码对应专属的返回类型
type OkResponse = {
  code: ErrorCode.OK;
  message: string;
  data: Person[]; // OK时data是Person数组
};

type MaximumExceededResponse = {
  code: ErrorCode.MAXIMUM_EXCEEDED;
  message: string;
  data: MaximumExceeded; // 超出限制时data是固定结构
};

type UnknownErrorResponse = {
  code: ErrorCode.UNKNOWN_ERROR;
  message: string;
  data?: never; // 未知错误无data,用never明确不需要
};

// 最终的Response是三个类型的联合
type Response = OkResponse | MaximumExceededResponse | UnknownErrorResponse;

2. 修改API函数的返回类型

让API函数的返回值类型为Promise<Response>,TypeScript会自动验证返回值是否符合联合类型的某个成员:

export async function api(id: string, maximum: number): Promise<Response> {
  try {
    if (maximum > 10) {
      return {
        code: ErrorCode.MAXIMUM_EXCEEDED,
        message: "maximum exceeded",
        data: {
          limit: 10,
          inclusive: false,
        },
      };
    }

    const result = await new Promise<Person[]>((resolve, reject) => {
      setTimeout(() => {
        resolve([
          {
            name: "Alice",
            age: 30,
          },
          {
            name: "Bob",
            age: 31,
          },
        ]);
      }, 1000);
    });

    return {
      code: ErrorCode.OK,
      message: "success",
      data: result,
    };
  } catch (e) {
    if (e instanceof Error) {
      return {
        code: ErrorCode.UNKNOWN_ERROR,
        message: e.message,
      };
    } else {
      return {
        code: ErrorCode.UNKNOWN_ERROR,
        message: "Unknown error",
      };
    }
  }
}

3. 调用时自动推导类型

现在调用API时,只要判断code的值,TypeScript会自动缩小返回值的类型,无需手动断言:

async function test() {
  const result = await api("123", 20);
  
  if (result.code === ErrorCode.OK) {
    // TypeScript自动推断result.data是Person[]
    console.log(result.data[0].name); // 直接访问,无类型错误
  } else if (result.code === ErrorCode.MAXIMUM_EXCEEDED) {
    // 自动推断result.data是MaximumExceeded
    console.log("limit", result.data.limit); // 直接访问limit
  } else {
    // 自动推断是UnknownErrorResponse,无data
    console.log(result.message);
  }
}

为什么要这么做?

原来的单一Response类型中,code是宽泛的ErrorCode枚举,data是any,TypeScript无法关联code和data的对应关系。而联合类型的每个成员都用字面量类型指定code,TypeScript可以通过code的判断进行类型窄化,自动识别对应的data结构,既保证类型安全,又无需手动写类型断言。

如果确实需要手动断言(比如特殊场景),也可以用类型断言语法:

// 手动断言为MaximumExceededResponse
const exceededResult = result as MaximumExceededResponse;
console.log(exceededResult.data.limit);

但优先推荐用类型窄化的方式,避免手动断言带来的类型风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:00:08