发布时间:2026/7/18 13:14:15
TypeScript错误处理:从基础到高级实践 1. TypeScript错误处理基础概念在TypeScript开发中错误处理是保证代码健壮性的关键环节。与JavaScript类似TypeScript使用相同的错误处理机制但通过静态类型检查提供了更强的安全保障。我们先来看最基本的错误处理结构try { // 可能抛出错误的代码 throw new Error(Something went wrong); } catch (error) { // 错误处理逻辑 console.error(error.message); } finally { // 无论是否出错都会执行的代码 console.log(Cleanup operations); }这种结构看似简单但在TypeScript中有几个关键特性需要注意错误对象默认类型为any这不符合TypeScript的类型安全理念。我们可以通过类型注解来改进catch (error: unknown) { if (error instanceof Error) { console.error(error.message); } else { console.error(Unknown error occurred); } }TypeScript支持自定义错误类这在实际项目中非常有用class NetworkError extends Error { constructor(public statusCode: number, message: string) { super(message); this.name NetworkError; } } try { throw new NetworkError(404, API not found); } catch (error) { if (error instanceof NetworkError) { console.error(HTTP ${error.statusCode}: ${error.message}); } }2. TypeScript特有的错误处理模式2.1 类型保护与错误处理TypeScript的类型系统可以与错误处理完美结合。考虑以下场景function parseJSON(json: string): unknown { return JSON.parse(json); } const result parseJSON({valid: false}); if (result typeof result object valid in result) { // 类型安全地访问result.valid console.log(result.valid); }这种模式避免了直接使用any类型同时提供了类型安全的错误处理。2.2 异步错误处理的最佳实践在异步代码中错误处理尤为重要。以下是几种常见模式Promise的catch处理fetchData() .then(data processData(data)) .catch((error: Error) { console.error(Fetch failed:, error.message); });async/await模式async function loadUserData(userId: string) { try { const response await fetch(/users/${userId}); if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } return await response.json(); } catch (error) { if (error instanceof Error) { console.error(Failed to load user:, error.message); } throw error; // 重新抛出以便上层处理 } }2.3 声明自定义错误类型对于大型项目定义一套完整的错误类型体系非常有用interface AppError { code: string; message: string; details?: unknown; } class ValidationError extends Error implements AppError { constructor(public code: string, message: string) { super(message); this.name ValidationError; } } function validateInput(input: string) { if (!input) { throw new ValidationError(INVALID_INPUT, Input cannot be empty); } }3. 高级错误处理技术3.1 错误边界与类型断言在React等前端框架中错误边界是处理组件错误的有效方式。在TypeScript中我们可以增强其类型安全性class ErrorBoundary extends React.Component{}, { hasError: boolean } { state { hasError: false }; static getDerivedStateFromError(error: unknown) { return { hasError: true }; } componentDidCatch(error: unknown, info: React.ErrorInfo) { logErrorToService(error, info.componentStack); } render() { if (this.state.hasError) { return FallbackUI /; } return this.props.children; } }3.2 函数式错误处理对于函数式编程风格我们可以使用Either模式type EitherL, R { left: L } | { right: R }; function safeParse(json: string): EitherError, unknown { try { return { right: JSON.parse(json) }; } catch (error) { return { left: error instanceof Error ? error : new Error(String(error)) }; } } const result safeParse(invalid json); if (left in result) { console.error(Parse failed:, result.left.message); } else { console.log(Parsed data:, result.right); }3.3 错误处理中间件在Express等后端框架中TypeScript可以增强错误中间件的类型安全interface ErrorRequestHandler P ParamsDictionary, ResBody any, ReqBody any, ReqQuery ParsedQs, Locals extends Recordstring, any Recordstring, any { ( err: any, req: RequestP, ResBody, ReqBody, ReqQuery, Locals, res: ResponseResBody, Locals, next: NextFunction ): void; } const errorHandler: ErrorRequestHandler (err, req, res, next) { if (err instanceof CustomError) { res.status(err.statusCode).json({ error: err.message, code: err.code }); } else { res.status(500).json({ error: Internal Server Error }); } };4. 实战中的错误处理技巧4.1 错误日志记录完善的错误日志是调试的关键。在TypeScript中我们可以创建类型安全的日志记录器interface LogEntry { timestamp: Date; level: error | warn | info; message: string; error?: Error; context?: Recordstring, unknown; } class Logger { log(entry: LogEntry) { console[entry.level]({ ...entry, timestamp: entry.timestamp.toISOString(), error: entry.error ? { name: entry.error.name, message: entry.error.message, stack: entry.error.stack } : undefined }); } }4.2 测试中的错误处理在单元测试中我们需要特别关注错误情况的测试describe(parseJSON, () { it(should throw for invalid JSON, () { expect(() parseJSON(invalid)).toThrow(SyntaxError); }); it(should return parsed data for valid JSON, () { const result parseJSON({valid:true}); expect(result).toEqual({ valid: true }); }); });4.3 性能考量错误处理对性能有一定影响特别是在热路径中避免在性能关键代码中使用try/catch对于可预测的错误使用返回码可能更高效错误对象的创建和堆栈跟踪收集是昂贵的操作// 不推荐在热路径中 function hotPath(input: string) { try { return process(input); } catch { return defaultValue; } } // 更高效的替代方案 function hotPath(input: string) { const result processIfValid(input); return result ! undefined ? result : defaultValue; }5. 常见错误处理模式对比5.1 抛出错误 vs 返回错误对象方法优点缺点适用场景抛出错误自动中断执行流强制处理性能开销大可能被忽略不可恢复的错误返回错误对象显式处理性能更好需要手动传播错误可恢复的错误5.2 不同错误处理库对比库名特点TypeScript支持适用场景neverthrow函数式风格Either模式优秀函数式项目ts-results简单的结果类型优秀小型项目fp-ts完整函数式工具集优秀大型函数式项目原生try/catch无需依赖一般简单场景5.3 错误处理策略选择指南前端UI使用错误边界和用户友好的错误提示API层返回结构化的错误响应服务层使用特定错误类型便于日志分析数据访问层将底层错误转换为领域错误6. TypeScript配置与错误处理6.1 tsconfig.json相关设置{ compilerOptions: { strict: true, noImplicitAny: true, strictNullChecks: true, useUnknownInCatchVariables: true } }这些设置可以增强错误处理的类型安全性useUnknownInCatchVariables将catch变量默认为unknown而非anystrictNullChecks防止null/undefined相关错误noImplicitAny避免隐式的any类型6.2 自定义类型守卫创建类型安全的错误判断函数function isErrorWithMessage(error: unknown): error is { message: string } { return typeof error object error ! null message in error typeof (error as any).message string; } try { // ... } catch (error) { if (isErrorWithMessage(error)) { console.error(error.message); } }6.3 声明合并增强Error通过声明合并为Error添加额外属性declare global { interface Error { code?: string; status?: number; } } const err new Error(Not found); err.code NOT_FOUND; err.status 404;7. 错误处理实用工具函数7.1 安全类型转换function safeCastT(value: unknown, guard: (v: unknown) v is T): T { if (guard(value)) { return value; } throw new TypeError(Value cannot be cast to target type); } // 使用示例 const isUser (v: unknown): v is User typeof v object v ! null id in v; try { const user safeCast(response.data, isUser); } catch (error) { console.error(Invalid user data); }7.2 重试机制async function withRetryT( operation: () PromiseT, maxRetries: number, delayMs: number ): PromiseT { let lastError: unknown; for (let i 0; i maxRetries; i) { try { return await operation(); } catch (error) { lastError error; if (i maxRetries - 1) { await new Promise(resolve setTimeout(resolve, delayMs)); } } } throw lastError instanceof Error ? lastError : new Error(String(lastError)); }7.3 错误聚合class AggregateError extends Error { constructor(public errors: Error[], message Multiple errors occurred) { super(message); this.name AggregateError; } } function parallelWithAggregateErrorT( tasks: (() PromiseT)[] ): PromiseT[] { return Promise.all(tasks.map(task task().catch(e e))) .then(results { const errors results.filter(isError); if (errors.length 0) { throw new AggregateError(errors); } return results as T[]; }); } function isError(value: unknown): value is Error { return value instanceof Error; }8. 错误处理与设计模式8.1 策略模式interface ErrorHandler { canHandle(error: unknown): boolean; handle(error: unknown): void; } class NetworkErrorHandler implements ErrorHandler { canHandle(error: unknown): boolean { return error instanceof Error error.message.includes(network); } handle(error: unknown) { if (!(error instanceof Error)) return; showToast(Network error, please check your connection); } } class ValidationErrorHandler implements ErrorHandler { canHandle(error: unknown): boolean { return error instanceof Error error.message.includes(validation); } handle(error: unknown) { if (!(error instanceof Error)) return; highlightInvalidFields(); } } const handlers: ErrorHandler[] [ new NetworkErrorHandler(), new ValidationErrorHandler() ]; function handleError(error: unknown) { const handler handlers.find(h h.canHandle(error)); if (handler) { handler.handle(error); } else { console.error(Unhandled error:, error); } }8.2 装饰器模式function withErrorHandling( target: any, propertyKey: string, descriptor: PropertyDescriptor ) { const originalMethod descriptor.value; descriptor.value async function(...args: any[]) { try { return await originalMethod.apply(this, args); } catch (error) { if (error instanceof Error) { console.error(Error in ${propertyKey}:, error.message); } throw error; } }; return descriptor; } class ApiService { withErrorHandling async fetchData(url: string) { const response await fetch(url); if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } return response.json(); } }8.3 工厂模式interface ErrorFactory { create(error: unknown): Error; } class HttpErrorFactory implements ErrorFactory { create(error: unknown): Error { if (typeof error object error ! null) { if (status in error typeof error.status number) { return new HttpError(error.status, String(error.message || HTTP Error)); } } return new Error(String(error)); } } class HttpError extends Error { constructor(public status: number, message: string) { super(message); this.name HttpError; } } function createErrorHandler(factory: ErrorFactory) { return function handleError(error: unknown) { const normalizedError factory.create(error); console.error(${normalizedError.name}: ${normalizedError.message}); return normalizedError; }; }9. 错误处理与性能监控9.1 错误追踪集成interface ErrorTracker { captureException(error: unknown, context?: Recordstring, unknown): void; } class SentryErrorTracker implements ErrorTracker { constructor(private dsn: string) {} captureException(error: unknown, context?: Recordstring, unknown) { if (error instanceof Error) { // 实际项目中会调用Sentry SDK console.error(Sentry captured:, error.message, context); } else { console.error(Sentry captured unknown error:, error, context); } } } function withErrorTracking( tracker: ErrorTracker, fn: (...args: any[]) Promiseany ) { return async function(...args: any[]) { try { return await fn(...args); } catch (error) { tracker.captureException(error, { args }); throw error; } }; }9.2 性能指标收集interface ErrorMetrics { increment(errorType: string): void; timing(method: string, duration: number, success: boolean): void; } class PrometheusErrorMetrics implements ErrorMetrics { increment(errorType: string) { console.log(Metric incremented: errors_${errorType}_total); } timing(method: string, duration: number, success: boolean) { console.log(Method ${method} took ${duration}ms (success: ${success})); } } function instrumentWithMetrics( metrics: ErrorMetrics, fn: (...args: any[]) Promiseany ) { return async function(...args: any[]) { const start Date.now(); try { const result await fn(...args); metrics.timing(fn.name, Date.now() - start, true); return result; } catch (error) { metrics.timing(fn.name, Date.now() - start, false); if (error instanceof Error) { metrics.increment(error.constructor.name); } else { metrics.increment(UnknownError); } throw error; } }; }10. 错误处理最佳实践总结始终使用Error对象不要抛出原始字符串或其他类型区分错误类型创建特定的错误类来表示不同类型的错误保持类型安全利用TypeScript的类型系统来增强错误处理适当处理异步错误确保Promise和async/await中的错误被正确处理提供有意义的错误信息包含足够的上下文以便调试考虑错误恢复策略对于可恢复错误提供恢复路径记录错误确保所有错误都被适当记录以便后续分析监控生产环境错误使用错误跟踪系统监控生产环境中的错误测试错误场景编写测试验证错误处理逻辑文档化错误约定在团队中建立一致的错误处理规范在实际项目中错误处理策略应该根据项目规模、团队偏好和具体需求进行调整。TypeScript提供的类型系统可以大大增强错误处理的安全性和可维护性关键是找到适合你项目的平衡点。

相关新闻

2026/7/18 13:14:15

Redis 3.x——配置统计字典

配置统计字典1、info系统状态说明1.1、命令说明1.2、详细说明1.2.1、Server1.2.2、Clients1.2.3、Memory1.2.4、Persistence1.2.5、Stats1.2.6、Replication1.2.7、CPU1.2.8、Commandstats1.2.9、Cluster1.2.10、Keyspace2、standalone配置说明和分析2.1、总体配置2.2、最大内存…

2026/7/18 13:14:15

STM32定时器PWM电子琴仿真:Proteus与Keil实战教程

这次我们来看一个基于STM32单片机的多音电子琴Proteus仿真项目。这个设计以STM32F103系列单片机为核心,通过七个琴键控制蜂鸣器演奏不同音区的音符(低音、中音、高音),使用LED指示灯实时反馈按键状态,并通过数码管显示…

2026/7/17 5:59:06

3步解锁音乐自由:ncmdumpGUI终极NCM文件解密转换指南

3步解锁音乐自由:ncmdumpGUI终极NCM文件解密转换指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾在网易云音乐下载了心爱的歌曲&#…

2026/7/18 10:53:38

CANoe 19 SP3 配置 GB/T 27930-2023 A类系统:3步搭建BMS仿真测试环境

CANoe 19 SP3 配置 GB/T 27930-2023 A类系统:3步搭建BMS仿真测试环境随着新能源汽车行业的快速发展,充电通信协议的标准化和测试验证变得尤为重要。GB/T 27930-2023作为中国智能充电协议的最新版本,对充电机与电动汽车之间的通信提出了更严格…

2026/7/17 7:39:19

3步搞定RTL8852BE驱动:从零开始配置Wi-Fi 6网卡

3步搞定RTL8852BE驱动:从零开始配置Wi-Fi 6网卡 【免费下载链接】rtl8852be Realtek Linux WLAN Driver for RTL8852BE 项目地址: https://gitcode.com/gh_mirrors/rt/rtl8852be 还在为Linux系统无法识别RTL8852BE Wi-Fi 6网卡而烦恼吗?&#x1f…

2026/7/18 0:00:24

某智驾大牛创业

作者:钟声编辑:Mark出品:红色星际头图:智能驾驶图片据悉,国内某头部智驾公司端到端模型技术大牛Z投身创业,并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈,更是业内…

2026/7/17 14:59:44

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…