如何在Immer更新Draft时动态添加新属性?解决TypeScript TS7053类型报错问题
解决Immer Draft动态添加属性的TypeScript类型报错问题
这个问题在使用Immer结合TypeScript时很常见——你想给draft动态添加原类型里没有的属性,但TypeScript会因为类型不匹配抛出TS7053错误,同时你又不想修改MyObject本身的定义。下面是几种可行的解决方案:
方案1:直接使用交叉类型断言
把draft断言为原类型和新属性的交叉类型,明确告诉TypeScript这个draft现在包含你要添加的属性:
const payload = produce(data, (draft) => { // 断言draft为包含newProperty的WritableDraft类型 (draft as WritableDraft<MyObject & { newProperty: string }>)['newProperty'] = 'test'; });
这种方式简单直接,适合只添加单个明确属性的场景。
方案2:提前定义扩展类型
如果需要多次使用这个扩展后的类型,先单独定义出来会更清晰:
// 定义原类型和新属性的交叉类型 type MyObjectWithNewProp = MyObject & { newProperty: string }; const payload = produce(data, (draft) => { (draft as WritableDraft<MyObjectWithNewProp>).newProperty = 'test'; });
这样代码可读性更高,后续如果要修改新属性的类型或添加更多属性,只需要修改MyObjectWithNewProp即可。
方案3:使用索引签名支持任意动态属性
如果需要添加多个不确定名称的动态属性,可以用Record类型给原类型加上索引签名:
const payload = produce(data, (draft) => { // 允许添加任意字符串键的未知类型属性 const typedDraft = draft as WritableDraft<MyObject & Record<string, unknown>>; typedDraft['newProperty'] = 'test'; typedDraft['anotherDynamicProp'] = 123; // 也能添加其他属性 });
这个方案灵活性最高,适合属性名不固定或者需要批量添加属性的场景,但会失去对新属性的严格类型检查,需要根据实际需求选择。
为什么会报错?
Immer生成的draft类型是基于你传入的data的类型(MyObject)生成的WritableDraft<MyObject>,TypeScript会严格校验这个类型的属性,不允许添加原类型中未定义的属性。我们通过类型断言绕开了这个校验,同时不需要修改原MyObject的定义。
内容的提问来源于stack exchange,提问作者me.at.coding
相关产品推荐
相关产品推荐

