TypeScript catch块中如何正确捕获非Error实例类型的抛出对象
TypeScript 捕获非Error实例的抛错解决方案
TypeScript 4.0及以上版本默认将catch子句捕获的错误类型设置为unknown,禁止直接访问任意属性,必须先完成类型收窄才能访问对应属性,以下是两种常用的处理方案:
方案1:自定义类型守卫(推荐,兼顾类型安全和运行时安全)
先定义抛出错误的结构,再编写运行时校验的类型守卫函数,确保类型判断同时符合编译时和运行时的要求:
// 定义自定义错误的类型结构 interface CustomError { code: number; message: string; } // 类型守卫函数,运行时校验传入值是否符合CustomError结构 function isCustomError(err: unknown): err is CustomError { return ( typeof err === 'object' && err !== null && 'code' in err && typeof (err as CustomError).code === 'number' && 'message' in err && typeof (err as CustomError).message === 'string' ); } // 实际使用示例 function throwsSomeError() { throw { code: 10, message: 'error' } } try { throwsSomeError() } catch (error: unknown) { if (isCustomError(error)) { // 此处TypeScript会自动将error收窄为CustomError类型,可正常访问属性 const message = error.message; const code = error.code; } else { // 可在此处处理其他非预期的错误类型 console.error('未知错误类型', error); } }
方案2:类型断言(仅推荐确定抛错结构的场景使用)
如果100%确定当前代码抛出的错误结构符合预期,不需要额外运行时校验,可以直接用类型断言收窄类型:
interface CustomError { code: number; message: string; } try { throwsSomeError() } catch (error: unknown) { const customError = error as CustomError; const message = customError.message; }
注意:该方案仅做编译时的类型转换,没有运行时校验,如果实际抛出的错误不符合CustomError结构,可能会引发运行时异常。
规范优化建议
更符合JavaScript错误处理规范的做法是自定义继承自Error类的错误类型,后续捕获时可以直接用instanceof做判断,代码更简洁:
class CustomError extends Error { code: number; constructor(code: number, message: string) { super(message); this.code = code; // 兼容TS继承内置类的原型链问题 Object.setPrototypeOf(this, CustomError.prototype); } } // 抛出时改为抛CustomError实例 function throwsSomeError() { throw new CustomError(10, 'error'); } try { throwsSomeError() } catch (error: unknown) { if (error instanceof CustomError) { const message = error.message; const code = error.code; } }
内容的提问来源于stack exchange,提问作者LonelyCpp
相关产品推荐
相关产品推荐

