TypeScript自定义Error类报错:无法设置对象X的只读属性'name'
问题原因
报错的核心诱因是你多余添加的__proto__ = Error类字段,具体逻辑如下:
- ES6 中
class extends语法已经自动完成了父子类的原型链配置,自定义继承Error的类时不需要手动修改原型。 - 类公共字段的执行时机是在派生类的
super()调用返回后、构造函数剩余代码执行前,你写的__proto__ = Error会在此时把当前错误实例的原型直接从BlockError.prototype修改为Error构造函数本身(注意不是Error.prototype,属于旧写法抄录错误)。 - Error是内置函数对象,它自身的
name属性是只读的(属性描述符writable: false)。后续执行this.name = "BlockError"时,JS引擎沿原型链找到这个只读属性,尝试赋值就会抛出类型错误。 - 报错信息里提到的
'Whoops!'是你传入的错误消息,是运行环境格式化错误对象时输出的实例标识,不是实际给字符串赋值。
另外你写的message: string类型标注也属于冗余代码,Error基类已经自带该属性的类型定义,部分编译配置下重复声明反而会引出额外问题。
可行解决方案
现代环境最简写法(推荐)
适用于所有现代浏览器、Node.js 6+ 等原生支持ES6 Class的环境,直接删除错误的原型赋值行即可:
class BlockError extends Error { constructor(message) { super(message); this.name = "BlockError"; // 可选:优化栈追踪信息,排除构造函数本身的调用帧 if (Error.captureStackTrace) { Error.captureStackTrace(this, BlockError); } } } // 测试代码 function test() { throw new BlockError("Whoops!"); } try { test(); } catch(e) { console.error(`${e.name}: ${e.message}\n${e.stack}`); console.log(e instanceof BlockError); // 输出true console.log(e instanceof Error); // 输出true }
老旧引擎兼容写法
如果需要兼容对Error继承支持有缺陷的老旧JS环境,可以在构造函数内用标准API修正原型,注意不要把原型指向Error构造函数本身:
class BlockError extends Error { constructor(message) { super(message); this.name = "BlockError"; // 修复老旧环境下原型链异常问题 Object.setPrototypeOf(this, BlockError.prototype); if (Error.captureStackTrace) { Error.captureStackTrace(this, BlockError); } } }
不要使用直接给
__proto__赋值的写法修改原型,非标准属性在不同环境下行为不一致,很容易引出难以排查的问题。
内容的提问来源于stack exchange,提问作者Archigan
相关产品推荐
相关产品推荐

