You need to enable JavaScript to run this app. 如何在@reduxjs/toolkit中用WritableDraft为reducer辅助函数标注draft类型
优惠活动
大模型
产品
解决方案
定价
更多

如何在@reduxjs/toolkit中用WritableDraft为reducer辅助函数标注draft类型

可复用Redux Toolkit Reducer辅助函数的TypeScript类型配置方案

该场景完全可以实现符合预期的类型标注,不存在无法配置的问题,出现找不到WritableDraft的报错,本质是对该类型的来源认知偏差导致的。

核心原理说明

WritableDraft是Immer库提供的核心类型,作用是将原本只读约束的状态类型,包装成适配Immer draft代理逻辑的可变类型,让开发者可以直接用可变写法修改draft,不需要手动展开不可变状态。
@reduxjs/toolkit本身完全基于Immer实现状态的可变更新能力,所有reducer接收到的draft参数,本质类型就是WritableDraft<对应的切片状态类型>。早期版本的@reduxjs/toolkit没有将Immer导出的WritableDraft类型做自身的公共导出,所以直接尝试从toolkit包导入该类型时,会出现类型不存在的报错。

正确实现路径

  • 兼容性最优的通用写法:直接从项目依赖的immer包导入WritableDraft类型即可,这个类型和toolkit内部使用的draft类型定义完全一致,不存在任何兼容问题。
    完整示例代码:
    // 先定义你的切片状态类型
    type MySliceState = {
      value: number;
      items: string[];
    };
    
    // 从immer导入WritableDraft类型
    import type { WritableDraft } from 'immer';
    
    // 可复用辅助函数的正确类型标注
    const helperFunction = (
      draft: WritableDraft<MySliceState>
    ): void => {
      // 这里对draft的修改会被TS正确识别,不会触发只读属性修改的报错
      draft.value += 1;
      draft.items.push('new entry');
    };
    
    // 在切片reducer中调用,无类型不匹配报错
    const mySlice = createSlice({
      name: 'mySlice',
      initialState: { value: 0, items: [] } as MySliceState,
      reducers: {
        MY_REDUCER(draft) {
          helperFunction(draft);
        }
      }
    });
    
  • 适配新版本Toolkit的写法:如果你使用的是1.9.0及以上版本的@reduxjs/toolkit,目前版本已经将WritableDraft做了公共导出,也可以直接从toolkit包导入该类型使用:
    import type { WritableDraft } from '@reduxjs/toolkit';
    
    注意:这种写法在旧版本toolkit中会出现类型找不到的问题,跨项目、跨版本开发时优先选择从immer导入的写法,兼容性更强。

常见踩坑提示

  • 不要直接把辅助函数的draft参数标注为原始的MySliceState类型,TS会将其识别为只读不可变状态,触发修改只读属性的类型报错。
  • 不需要手动手写实现WritableDraft的类型定义,很容易和内部实现的类型层级不匹配,导致复杂嵌套状态的类型校验报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 14:15:04