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

TypeScript中如何使用扩展运算符更新现有对象的引用?

如何更优雅地更新TypeScript中接口定义对象的类实例引用?

我有一个由接口定义结构的对象,里面存了多个类实例,代码如下:

class S1 { n: number; }
class S2 { n: number; }
class S3 { n: number; }
interface State { s1: S1; s2: S2; s3: S3; }
var Store: State = { s1: new S1(), s2: new S2(), s3: new S3(), }

之前我是通过创建新实例再赋值的方式修改:

var s1 = new S1();
s1.n = 4;
Store.s1 = s1;

现在我知道可以用Store["s1"] = { ...Store["s1"] };来更新引用,但想找更优雅的实现方式。


几种更优雅的实现思路

1. 直接修改属性(最省事的场景)

如果你只是要更新实例里的属性值,完全没必要替换整个引用啊!直接改属性就行:

Store.s1.n = 4;

这种方式不用创建新实例,性能好还直观,适合只改属性的情况。

2. 正确复制类实例(别丢了原型链)

你之前用{ ...Store["s1"] }的方式有个坑:新对象不是S1的实例,因为展开运算符只会复制实例自身的属性,原型链没了。如果确实需要替换整个引用,同时保留类的原型(比如类里有方法的话),可以这么搞:

首先给类加个支持初始化参数的构造函数:

class S1 {
  n: number;
  // 支持传入部分属性初始化
  constructor(init?: Partial<S1>) {
    Object.assign(this, init);
  }
}

然后创建新实例的时候直接复用原有属性:

Store.s1 = new S1({ ...Store.s1, n: 4 });

要是不想改类的构造函数,也可以用Object.create保留原型:

const oldInstance = Store.s1;
Store.s1 = Object.create(Object.getPrototypeOf(oldInstance));
Object.assign(Store.s1, oldInstance, { n: 4 });

这样新对象依然是S1的实例,不会丢原型上的方法。

3. 封装通用函数(频繁更新时省代码)

如果要经常更新不同的实例,写个通用函数能省不少重复代码:

function updateStore<T extends keyof State>(key: T, updates: Partial<State[T]>) {
  // 获取对应实例的构造函数
  const Constructor = Store[key].constructor as new () => State[T];
  // 创建新实例,合并原有属性和更新内容
  const newInstance = new Constructor();
  Object.assign(newInstance, Store[key], updates);
  // 更新Store里的引用
  Store[key] = newInstance;
}

// 用的时候就很简单:
updateStore('s1', { n: 4 });
updateStore('s2', { n: 10 });

这个函数自动对应每个key的类,不用每次都手动new,复用性拉满。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:05:22