TypeScript 错误处理:从 try/catch 到复杂场景
TypeScript 作为 JavaScript 的超集,继承并扩展了错误处理机制。正确的异常处理是构建稳定且可预测应用程序的关键。本文将全面解析错误处理的各个方面:从基础的 try/catch 到创建自定义类型化错误类以及高级策略。
基本语法:try, catch, finally
TypeScript(以及 JavaScript)中主要的错误处理机制是 try...catch...finally 结构。它允许捕获代码中出现的异常并做出响应。
function parseJSON(data: string): object { try { return JSON.parse(data); } catch (error) { console.error('JSON 解析错误:', error); return {}; }}
parseJSON('{"name": "TypeScript"}'); // { name: 'TypeScript' }parseJSON('无效的 JSON'); // {} (错误已被捕获)finally 块在任何情况下都会执行——无论是在 try 成功完成后,还是在捕获错误之后。这是清理资源(关闭文件、连接)的理想位置。
function processData(data: string): void { let resource: any = null; try { resource = acquireResource(); // ... 危险代码 } catch (error) { console.error('处理错误:', error); } finally { if (resource) { resource.release(); // 确保清理 } }}错误类型化:unknown 问题
TypeScript 的一个关键特性是:在 catch 块中,error 变量默认具有 unknown 类型(从 TS 4.0 开始)。这是有意为之,旨在强制开发者显式检查错误类型,而不是假设它是 Error。
try { // 某些代码} catch (error) { // error 的类型是 unknown // 错误:类型 'unknown' 上不存在属性 'message' // console.log(error.message);
// 正确方法——类型检查 if (error instanceof Error) { console.log('消息:', error.message); } else { console.log('未知错误:', error); }}为什么这很重要?在 JavaScript 中,catch 块可以捕获任何内容:字符串、数字、对象、null 甚至 undefined。强制类型检查可以防止运行时错误。
创建自定义错误类
对于复杂应用程序,通常需要区分不同类型的错误。在 TypeScript 中,可以轻松创建扩展内置 Error 的自定义错误类层次结构。
// 应用程序错误基类class AppError extends Error { public readonly statusCode: number; public readonly isOperational: boolean;
constructor(message: string, statusCode: number = 500, isOperational: boolean = true) { super(message); this.name = this.constructor.name; this.statusCode = statusCode; this.isOperational = isOperational;
// 恢复原型(对于 instanceof 很重要) Object.setPrototypeOf(this, new.target.prototype); }}
// 具体错误类型class ValidationError extends AppError { public readonly field: string;
constructor(message: string, field: string) { super(message, 400); this.field = field; }}
class NotFoundError extends AppError { constructor(message: string = '资源未找到') { super(message, 404); }}
// 使用示例function getUser(id: number): User { if (id <= 0) { throw new ValidationError('ID 必须为正数', 'id'); } // ... 查找用户 throw new NotFoundError