跨库共用自定义Error时使用instanceof做类型校验是否安全?
结论先行
你写的instanceof判断不可靠,其有效性确实依赖npm安装依赖时是否对多份相同依赖做了复用。
核心原理
instanceof的判断逻辑是检查错误实例的原型链上,是否存在对应构造函数的prototype属性。如果项目中出现多份@so/errors拷贝,不同拷贝导出的CustomError是完全独立的函数对象,对应的prototype属性也不是同一个引用,此时从其他拷贝的CustomError生成的实例,用当前拷贝的构造函数做instanceof判断就会返回false,哪怕两个CustomError的代码逻辑完全一致。
版本依赖要求
是的,只有你项目中直接依赖的@so/errors版本,和@so/doSomething、@so/doSomething2依赖的@so/errors版本完全匹配、或者在semver兼容范围内可以共用同一份版本时,npm才会把@so/errors提升到项目根目录的node_modules下,三者共用同一份代码,此时instanceof判断才能正常生效。
如果版本范围不兼容,npm会在@so/doSomething或@so/doSomething2的私有node_modules目录下单独安装对应版本的@so/errors,此时就会出现多份拷贝,导致判断失效。哪怕版本完全一致,遇到依赖树嵌套、包管理器lock文件异常等特殊情况,也有可能出现多份拷贝的问题。
更稳妥的替代方案
如果要做兼容多拷贝场景的错误判断,推荐用以下方案替代instanceof:
- 给自定义错误类添加唯一标识属性:
// 库A @so/errors 中的定义 class CustomError extends Error { name = 'CustomError' // 也可以用Symbol避免命名冲突 static [Symbol.for('CustomError')] = true static isCustomError = (err) => { return err?.name === 'CustomError' || err?.constructor?.[Symbol.for('CustomError')] } }
- 捕获错误时直接判断标识即可,不受多份拷贝影响:
if (CustomError.isCustomError(err)) { console.log('caught!'); }
- 发布依赖
@so/errors的公共包时,将@so/errors声明为peerDependency,强制下游项目统一安装该依赖,也能大大降低多份拷贝出现的概率。
内容的提问来源于stack exchange,提问作者neverendingqs
相关产品推荐
相关产品推荐

