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

React Native升级后Jest测试报错:无法赋值只读prototype属性

问题:React Native升级至0.71.x后Jest单元测试因NetworkError原型赋值失败

报错信息

TypeError: Cannot assign to read only property 'prototype' of function 'function NetworkError(message, code) {
      var name = arguments.length > 2 && arguments[2] !== undefined ? argume...<omitted>...
    }'

      19 |   }
      20 | }
    > 21 | NetworkError.prototype = Object.create(Error.prototype);

现有NetworkError代码

export class NetworkError {
  public message: string | null;
  public name: string;
  public code: number;

  constructor(
    message: string | null,
    code: number,
    name: string = 'NetworkError',
  ) {
    this.message = message;
    this.name = name;
    this.code = code;
  }
}
NetworkError.prototype = Object.create(Error.prototype);

当前依赖版本

"dependencies": {
    "react": "18.2.0",
    "react-native": "0.71.11"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@babel/preset-env": "^7.20.0",
    "@babel/runtime": "^7.20.0",
    "@react-native-community/eslint-config": "^3.2.0",
    "@tsconfig/react-native": "^2.0.2",
    "@types/jest": "^29.2.1",
    "@types/react": "^18.0.24",
    "@types/react-test-renderer": "^18.0.0",
    "babel-jest": "^29.2.1",
    "eslint": "^8.19.0",
    "jest": "^29.2.1",
    "metro-react-native-babel-preset": "0.73.10",
    "prettier": "^2.4.1",
    "react-test-renderer": "18.2.0",
    "typescript": "4.8.4"
  },

解决方案

方案1:改用ES6类继承Error(推荐)

直接让NetworkError继承原生Error,自动继承原型链,避免手动赋值prototype的问题:

export class NetworkError extends Error {
  public code: number;

  constructor(
    message: string | null,
    code: number,
    name: string = 'NetworkError',
  ) {
    super(message ?? undefined); // 调用Error构造函数传递message
    this.name = name; // 覆盖Error默认的name属性
    this.code = code;
    
    // 修复部分环境下的原型链问题(如旧版Node.js)
    Object.setPrototypeOf(this, NetworkError.prototype);
  }
}

方案2:合并原型属性而非替换整个prototype

如果因循环依赖等原因无法使用继承,可通过Object.assign将Error原型的属性合并到NetworkError原型上,而非直接替换:

export class NetworkError {
  public message: string | null;
  public name: string;
  public code: number;

  constructor(
    message: string | null,
    code: number,
    name: string = 'NetworkError',
  ) {
    this.message = message;
    this.name = name;
    this.code = code;
  }
}

// 合并Error原型的属性到NetworkError原型
Object.assign(NetworkError.prototype, Error.prototype);
// 保留NetworkError自身的constructor属性
Object.defineProperty(NetworkError.prototype, 'constructor', {
  value: NetworkError,
  enumerable: false,
});

方案3:使用Object.setPrototypeOf设置原型链

通过Object.setPrototypeOf修改原型链,替代直接赋值prototype的操作:

export class NetworkError {
  public message: string | null;
  public name: string;
  public code: number;

  constructor(
    message: string | null,
    code: number,
    name: string = 'NetworkError',
  ) {
    this.message = message;
    this.name = name;
    this.code = code;
  }
}

// 设置NetworkError的原型继承自Error.prototype
Object.setPrototypeOf(NetworkError.prototype, Error.prototype);

原因说明

ES6类的prototype属性是只读的,直接赋值NetworkError.prototype = ...会触发TypeError。React Native 0.71+版本升级了Babel/TypeScript编译配置,严格遵循ES规范,因此旧代码中的手动替换prototype操作不再被允许。

内容的提问来源于stack exchange,提问作者dlc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:35:04