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

如何限制TypeScript函数返回的联合类型并抛出异常?

问题描述

我写了一个工具函数,用来解析API异常并返回建模后的TypeScript类型:

interface NotFoundException {
  type: 'notFound'
}

interface PermissionException {
  type: 'permission'
}

interface BadRequestException {
  type: 'badRequest'
}

// API错误的示例结构
interface APIError {
  statusCode: number;
}

type KnownExceptions = NotFoundException | PermissionException | BadRequestException;

function exceptionHandler(err: unknown): KnownExceptions {
  const statusCode = (err as APIError).statusCode ?? -1;

  if (statusCode === 404) {
    return {
      type: 'notFound'
    }
  }

  if (statusCode === 403) {
    return {
      type: 'permission'
    }
  }

  if (statusCode === 400) {
    return {
      type: 'badRequest'
    }
  }

  throw new Error('Unknown error', { cause: err });
}

但有些API不会抛出所有类型的异常,所以我需要显式处理那些不需要的异常类型:

interface APIInput {
  prop: string;
}

interface APIOutput {
  id: string;
}

function callAPI(input: APIInput): APIOutput | PermissionException | NotFoundException {
  try {
    // 模拟API调用
    return {
      id: 'id'
    };
  } catch (err: unknown) {
    const e = exceptionHandler(err);

    // 问题:这个API(以及其他一些API)不会抛出这类异常
    // 需要一个函数来限制exceptionHandler的返回类型,
    // 并对不可能出现的情况抛出「Unexpected exception」错误
    if (e.type === 'badRequest') {
      throw new Error('Unexpected exception', { cause: err });
    }

    return e;
  }
}

我想知道能不能写一个通用函数,把异常联合类型的返回值限制为我需要的类型,对其他所有类型抛出「Unexpected exception」错误?因为TypeScript不能把类型当作参数传递,我不知道该怎么实现。

解决方案

可以通过泛型函数结合类型守卫实现这个通用过滤逻辑,利用异常的type属性作为判断标识,过滤出允许的异常类型,不符合的直接抛出指定错误。

通用过滤函数实现

// 提取KnownExceptions中所有可能的type值类型
type ExceptionType = KnownExceptions['type'];

/**
 * 过滤异常,仅保留指定类型,其余抛出Unexpected exception
 * @param exception 待过滤的异常实例
 * @param allowedTypes 允许的异常type列表
 * @returns 符合要求的异常实例,类型自动匹配允许的类型
 */
function filterAllowedExceptions<T extends ExceptionType>(
  exception: KnownExceptions,
  allowedTypes: T[]
): Extract<KnownExceptions, { type: T }> {
  if (allowedTypes.includes(exception.type as T)) {
    return exception as Extract<KnownExceptions, { type: T }>;
  }
  throw new Error('Unexpected exception', { cause: exception });
}

在API调用中使用

把之前手动判断的逻辑替换成这个函数,代码更简洁且通用:

function callAPI(input: APIInput): APIOutput | PermissionException | NotFoundException {
  try {
    return { id: 'id' };
  } catch (err: unknown) {
    const e = exceptionHandler(err);
    // 只保留notFound和permission类型的异常
    return filterAllowedExceptions(e, ['notFound', 'permission']);
  }
}

类型安全保障

  • TypeScript会根据传入的allowedTypes自动推断返回的异常类型,确保类型和实际返回值一致。
  • 如果传入的allowedTypes包含不存在的异常type,TypeScript会直接报错,避免手动写错。
  • 非允许类型的异常会被直接抛出,不会流入后续逻辑,保证业务代码只处理预期内的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:51:08