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
相关产品推荐
相关产品推荐

