如何限制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
相关产品推荐
相关产品推荐

