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

通过对象实例化PaymentCoordinator类时categories属性无法设置问题

问题原因与解决方案

核心原因

你遇到的问题本质是TypeScript私有属性的特性导致的:
当你在构造函数参数前添加private修饰符时,TypeScript会自动将这些参数转换为类的私有实例字段(编译为ES标准的私有字段#categories,或旧版中不可枚举的命名空间属性)。这类私有属性有两个关键特性:

  1. Object.assign无法复制私有字段,因为它只会处理对象的可枚举自有属性,而私有字段不可枚举且外部无法直接访问;
  2. 若obj是普通对象(而非PaymentCoordinator类实例),直接赋值this.categories = obj.categories时,实际是在实例上新增了一个普通的categories属性,但TypeScript会优先让你访问类的私有字段#categories,导致你看起来赋值没生效。

另外,你的构造函数参数顺序也有问题:前面的categories参数没有默认值,当你调用构造函数进行克隆时,必须传入该参数(哪怕是undefined),这会先初始化私有字段为传入的值,后续的赋值操作可能被覆盖或无法正确映射到私有字段上。

解决方法

方法1:手动克隆所有私有属性(推荐)

放弃依赖Object.assign,手动复制每个属性,确保私有字段能正确被赋值,同时还能避免数组的引用问题:

constructor(
  private amount: number,
  private description: string,
  private title: string,
  private transactionType: string,
  private creditors: Array<any>,
  private categories: Array<string>,
  private startdate: Date = undefined,
  private enddate: Date = undefined,
  obj: any = false
) {
  if (obj) {
    // 手动覆盖所有属性,确保私有字段被正确赋值
    this.amount = obj.amount;
    this.description = obj.description;
    this.title = obj.title;
    this.transactionType = obj.transactionType;
    this.creditors = [...obj.creditors]; // 浅拷贝数组,避免引用共享
    this.categories = [...obj.categories]; // 同理处理categories
    this.startdate = obj.startdate ? new Date(obj.startdate) : undefined;
    this.enddate = obj.enddate ? new Date(obj.enddate) : undefined;
  }
}

方法2:调整构造函数逻辑顺序

将克隆逻辑放在参数初始化之前,确保私有字段被克隆值覆盖:

constructor(
  obj: any = false,
  private amount: number = 0,
  private description: string = '',
  private title: string = '',
  private transactionType: string = '',
  private creditors: Array<any> = [],
  private categories: Array<string> = [],
  private startdate: Date = undefined,
  private enddate: Date = undefined
) {
  if (obj) {
    // 先处理克隆,覆盖默认参数初始化的值
    Object.assign(this, obj);
    // 单独处理数组,避免引用问题
    this.categories = obj.categories ? [...obj.categories] : [];
  }
}

方法3:弱化属性访问限制

如果不需要严格的私有访问控制,可以将private修饰符改为protected,或者直接去掉,让属性成为普通可枚举属性,这样Object.assign就能正常复制所有属性:

constructor(
  amount: number,
  description: string,
  title: string,
  transactionType: string,
  creditors: Array<any>,
  categories: Array<string>,
  startdate: Date = undefined,
  enddate: Date = undefined,
  obj: any = false
) {
  // 手动将参数挂载为实例属性
  this.amount = amount;
  this.description = description;
  this.title = title;
  this.transactionType = transactionType;
  this.creditors = creditors;
  this.categories = categories;
  this.startdate = startdate;
  this.enddate = enddate;

  if (obj) {
    Object.assign(this, obj);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:18:55