如何不使用any类型告知TS try/catch捕获的错误含指定属性
报错原因
- TypeScript 4.0 及以上版本中,
catch语句捕获的错误参数默认类型为unknown,必须经过明确的类型收窄才允许访问属性。 - 现有判断逻辑仅能将
e的类型收窄为 TypeScript 内置的object类型,该类型仅标记值为非原始类型,不包含任何自定义属性的定义;同时原生hasOwnProperty调用默认不会触发 TypeScript 的属性级类型收窄,因此编译器无法识别data属性的存在,抛出ts(2339)错误。
无
any类型的合规解决方案 方案1:类型守卫(推荐,类型安全性最高)
提前定义目标错误的结构类型,编写带类型谓词的守卫函数,TypeScript 会根据守卫判断结果自动完成类型收窄,无需手动断言:
// 根据实际业务场景定义data的具体类型即可,这里用unknown做最宽松的安全类型 interface BusinessError { data: unknown; } /** * 校验错误对象是否为带data属性的业务错误 */ function isBusinessError(err: unknown): err is BusinessError { return ( typeof err === "object" && err !== null && "data" in err ); } // 业务代码使用 try { // 业务逻辑 } catch (e) { if (isBusinessError(e)) { // 此处e的类型自动收窄为BusinessError,可直接访问data属性,无TS报错 console.log(e.data); } }
如果需要严格校验属性为对象自有属性(而非原型链继承属性),可以将守卫中的属性判断逻辑替换为 Object.prototype.hasOwnProperty.call(err, "data"),类型收窄效果完全一致。
方案2:块级类型断言(适合轻量场景,无额外抽象)
如果不想抽离通用守卫函数,可以在判断分支内将e断言为提前定义的具体结构类型,全程不使用any,类型安全可控:
interface BusinessError { data: unknown; } try { // 业务逻辑 } catch (e) { if (typeof e === "object" && e !== null && "data" in e) { // 仅在当前判断块内做类型断言,作用域可控 console.log((e as BusinessError).data); } }
避坑说明
- 不要直接将
e断言为any,会完全丢失类型校验能力,违反类型安全规范 - 不要手动给catch参数标注为内置
Error类型,内置Error类型本身没有data属性定义,依然会触发属性不存在的报错 - 尽量使用
"key" in obj语法做属性存在判断,TypeScript 对该语法的类型收窄支持远好于原生hasOwnProperty调用
内容的提问来源于stack exchange,提问作者Madison Reibel
相关产品推荐
相关产品推荐

