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

Dart增强枚举作为Map键时抛出无法修改不可变Map异常

异常原因

这个报错和枚举从扩展方法迁移到增强枚举没有直接关系,触发点有两个:

  • VgnItmCache是freezed生成的不可变类,默认所有属性都是final,且freezed会对传入的集合类型参数做不可变包装,直接修改实例上的集合属性本身就违反freezed的设计约定。
  • 你在$localFetch中通过Map.map()生成的populatedVgnItms本身就是不可修改的Map视图:Dart中Map.map()、集合的toMap()这类转换方法默认返回的都是不可修改集合,你将这个Map通过copyWith传入后,freezed不会主动将其转为可修改集合,后续执行下标赋值操作时就会抛出Cannot modify unmodifiable map错误。
修复方法

优先推荐符合freezed不可变设计的方案,不要强行修改集合的可变性破坏数据一致性:

方案1(推荐):通过copyWith返回新实例

修改setVgnItm方法,不要直接修改原有实例的vgnItms属性,而是基于原有值生成新Map,再通过copyWith返回更新后的新缓存实例:

VgnItmCache setVgnItm({required VgnItm vgnItm, VgnItmType? type}) {
  final theType = type ?? myVgnItmType;
  // 复制原有Map为可修改的新实例
  final updatedVgnItms = Map<VgnItmType, VgnItmEst>.from(vgnItms ?? const {});
  updatedVgnItms[theType] = updatedVgnItms[theType]!.copyWith(vgnItm: vgnItm);
  // 返回更新后的新缓存实例,调用方需要用这个新实例替换旧实例
  return copyWith(vgnItms: updatedVgnItms);
}

方案2:显式声明可变集合(不推荐,破坏不可变特性)

如果你确实需要直接修改实例上的Map属性,需要做两处修改:

  1. 生成populatedVgnItms时主动将其转为可修改Map:
final populatedVgnItms = Map<VgnItmType, VgnItmEst>.from(
  VgnItmType.items.map((k, v) {
    return MapEntry(k, cache.vgnItms?[k] ?? VgnItmEst.empty(k));
  })
);
  1. 给vgnItms字段添加@Mutable()注解,告诉freezed不要对这个字段做不可变包装:
const factory VgnItmCache(
    {
    @Mutable() Map<VgnItmType, VgnItmEst>? vgnItms,
    @Default(<S3ImageCommand>[]) List<S3ImageCommand> s3ImageCommands,
    Option? vgnItmType,
    FormType? formType,
    @JsonKey(ignore: true) Ref? provider}) = _VgnItmCache;

额外提示:你迁移后的增强枚举代码中,静态items Map的两个元素之间缺少分隔逗号,会触发语法错误,记得补上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:51:23