TypeScript 中的高级错误处理:从 try/catch 到类型安全解决方案
错误处理是 TypeScript 开发中至关重要的方面。基础的 try/catch 对于复杂应用往往不够用。本文将介绍一些高级技术,帮助代码更可靠、可预测且类型安全。
1. 标准 try/catch 的问题:类型丢失
经典 catch 的主要缺点是错误变量的类型为 unknown(在旧版本中为 any)。这迫使开发者手动检查类型:
try { riskyOperation();} catch (error) { // error: unknown if (error instanceof Error) { console.error(error.message); } else { console.error('未知错误', error); }}解决方案:创建用于类型化错误捕获的工具函数:
function getErrorMessage(error: unknown): string { if (error instanceof Error) return error.message; if (typeof error === 'string') return error; if (error && typeof error === 'object' && 'message' in error) { return String((error as { message: unknown }).message); } return '发生了未知错误';}
try { riskyOperation();} catch (error) { console.error(getErrorMessage(error));}2. 带有类型化数据的自定义错误类
创建错误层次结构可以精确定位问题并传递额外数据:
// 基类class AppError extends Error { constructor( message: string, public readonly code: number, public readonly isOperational: boolean = true ) { super(message); this.name = 'AppError'; }}
// 专用错误class ValidationError extends AppError { constructor( message: string, public readonly field: string, public readonly invalidValue: unknown ) { super(message, 400); this.name = 'ValidationError'; }}
class NotFoundError extends AppError { constructor(entity: string, id: string) { super(`${entity} 未找到,ID 为 ${id}`, 404, false); this.name = 'NotFoundError'; }}
// 使用function findUser(id: string): User { if (!validateId(id)) { throw new ValidationError('无效的 ID', 'id', id); } const user = db.findUser(id); if (!user) { throw new NotFoundError('用户', id); } return user;}
try { const user = findUser('123');} catch (error) { if (error instanceof NotFoundError) { // error.code === 404, error.message 包含描述 console.warn(error.message); } else if (error instanceof ValidationError) { // error.field 和 error.invalidValue 可用 console.error(`字段 ${error.field} 错误:${error.message}`); } else if (error instanceof AppError) { console.error(`应用错误(代码 ${error.code}):${error.message}`); }}3. 用于错误处理的判别联合类型
这种模式允许在不使用异常的情况下处理操作结果,使用带有判别器的联合类型:
// 带有判别器的结果类型type Result<T, E = Error> = | { success: true; data: T } | { success: false; error: E };
// 返回 Result 的函数function safeDivide(a: number, b: number): Result<number, string> { if (b === 0) { return { success: false, error: '除以零' }; } return { success: true, data: a / b };}
// 使用const result = safeDivide(10, 0);
if (result.success) { // TypeScript 知道 result.data 是 number 类型 console.log(`结果:${result.data}`);} else { // result.error 是 string 类型 console.error(`错误:${result.error}`);}
// 带有自定义错误的更复杂示例type UserResult = Result<