TypeScript 中的错误处理:从基础 try/catch 到工业级模式
\n\n错误处理不仅仅是 try/catch 块。在 TypeScript 中,得益于严格的类型系统,我们可以将错误管理提升到一个全新的水平。在本文中,我们将探讨一些高级技术,帮助您编写更可靠、更可预测的代码。
标准 try/catch 在 TypeScript 中的问题
\n\n经典的 try/catch 块在 TypeScript 中有一个根本性问题:捕获的错误类型是 unknown(在旧版本中是 any)。这意味着 TypeScript 不知道我们正在处理的具体对象是什么。
try {\n // 一些危险代码\n const result = JSON.parse('{"data": 123}');\n} catch (error) {\n // error 的类型是 unknown\n // 不能直接调用 error.message\n console.log(error.message); // 编译错误!\n}\n\n这迫使开发者要么忽略类型,要么编写冗长的检查。让我们看看如何在高级层面上解决这个问题。
\n\n1. 创建带类型化的自定义错误系统
\n\n不要抛出普通的 Error,而是创建自定义错误的层次结构。这将允许 TypeScript 在编译时区分错误类型。
// 所有应用程序错误的基础类\nclass AppError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly statusCode: number = 500\n ) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n// 具体的错误类型\nclass ValidationError extends AppError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n }\n}\n\nclass NotFoundError extends AppError {\n constructor(resource: string) {\n super(`${resource} 未找到`, 'NOT_FOUND', 404);\n }\n}\n\nclass DatabaseError extends AppError {\n constructor(message: string) {\n super(message, 'DB_ERROR', 500);\n }\n}\n\n// 使用\nfunction findUser(id: string): User {\n if (!id) throw new ValidationError('ID 是必填项');\n // ... 查找逻辑\n if (!user) throw new NotFoundError('用户');\n return user;\n}\n\n2. 用于错误处理的类型守卫
\n\n为了安全地处理不同类型的错误,请使用类型守卫。这是处理 catch 中 unknown 的关键模式。
// AppError 的类型守卫\nfunction isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n\n// ValidationError 的类型守卫\nfunction isValidationError(error: unknown): error is ValidationError {\n return error instanceof ValidationError;\n}\n\n// 高级处理\ntry {\n const user = findUser(userId);\n} catch (error) {\n if (isValidationError(error)) {\n // TypeScript 知道 error 是 ValidationError\n console.error(`验证错误:${error.message}`);\n return { status: 400, message: error.message };\n }\n \n if (isAppError(error)) {\n // error 是 AppError\n console.error(`错误代码:${error.code}`);\n return { status: error.statusCode, message: error.message };\n }\n \n // 未知错误\n if (error instanceof Error) {\n console.error('未知错误:', error.message);\n }\n \n return { status: 500, message: '服务器内部错误' };\n}\n\n3. Result 模式(Either 单子)
\n\n这是异常的替代方案,它使错误处理在类型级别上变得明确。函数不是抛出错误,而是返回一个可以包含成功结果或错误的对象。
\n\n// Result 模式的类型定义\ntype Success<T> = { success: true; data: T };\ntype Failure<E> = { success: false; error: E };\ntype Result<T, E> = Success<T> | Failure<E>;\n\n// 辅助函数\nfunction success<T>(data: