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

使用immutability-helper+TypeScript时$merge报错,求原因与解决方法

解决immutability-helper结合TypeScript使用$merge更新Map中对象的编译错误

错误原因分析

你遇到的编译错误核心在于immutability-helper的类型系统与你使用的Map<string, Update>类型不兼容。

你之前尝试的写法把games当成了普通的索引式对象(用[x: string]来指定路径),但实际上games是原生的Map集合类型。immutability-helper默认的Spec类型定义只针对普通对象/数组设计了$merge、$set这类操作符的类型支持,直接用对象索引的方式描述Map的更新路径,TypeScript会检测到类型不匹配——它认为你在试图把Map转换成普通对象,自然会抛出类型不兼容的错误。

可行的$merge实现方案

要正确更新Map中指定key的对象属性,我们需要结合$apply操作符(用来处理Map这类非普通对象的不可变更新)和嵌套的$merge来实现。具体代码如下:

import update from 'immutability-helper';

// 假设你已有一个Updater实例
const initialUpdater: Updater = new Updater();
const targetGameKey = "your-game-key-here";
const newProgress = 50;

const updatedUpdater = update(initialUpdater, {
  games: {
    $apply: (currentGamesMap) => {
      // 先获取目标游戏的Update对象
      const targetUpdate = currentGamesMap.get(targetGameKey);
      if (!targetUpdate) {
        // 如果目标key不存在,直接返回原Map(保持不可变性)
        return currentGamesMap;
      }
      // 用$merge更新targetUpdate的progress属性,生成新对象
      const updatedGameUpdate = update(targetUpdate, {
        $merge: { progress: newProgress }
      });
      // 返回一个新的Map,替换目标key的对象(保证不可变性)
      return new Map(currentGamesMap).set(targetGameKey, updatedGameUpdate);
    }
  }
});

代码说明

  1. $apply操作符:专门用于处理非普通对象(比如Map、Set或者自定义类实例)的不可变更新,它接收当前值并返回一个新的不可变值。
  2. Map的不可变更新:我们通过new Map(currentGamesMap)创建原Map的副本,再用set方法替换目标key的对象,这样不会修改原Map。
  3. 嵌套的$merge:对Map中取出的Update对象使用$merge,只更新需要修改的progress属性,无需传入所有属性,完美解决了你担心的“属性较多时不便”的问题。

可选优化:自定义Map操作符

如果你的项目中经常需要更新Map中的对象,可以自定义一个专门的操作符来简化代码:

import update, { extend } from 'immutability-helper';

// 自定义$mapMerge操作符,用于更新Map中指定key的对象
extend('$mapMerge', function(
  currentMap: Map<string, any>,
  args: { key: string; mergeObj: Record<string, any> }
) {
  const target = currentMap.get(args.key);
  if (!target) return currentMap;
  const updatedTarget = update(target, { $merge: args.mergeObj });
  return new Map(currentMap).set(args.key, updatedTarget);
});

// 使用自定义操作符的简化写法
const updatedUpdater = update(initialUpdater, {
  games: {
    $mapMerge: { key: targetGameKey, mergeObj: { progress: newProgress } }
  }
});

这样后续更新Map中的对象时,代码会更简洁直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:48:14