You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 16:33:40