如何在@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包导入该类型使用:
注意:这种写法在旧版本toolkit中会出现类型找不到的问题,跨项目、跨版本开发时优先选择从immer导入的写法,兼容性更强。import type { WritableDraft } from '@reduxjs/toolkit';
常见踩坑提示
- 不要直接把辅助函数的draft参数标注为原始的
MySliceState类型,TS会将其识别为只读不可变状态,触发修改只读属性的类型报错。 - 不需要手动手写实现
WritableDraft的类型定义,很容易和内部实现的类型层级不匹配,导致复杂嵌套状态的类型校验报错。
内容的提问来源于stack exchange,提问作者cbdeveloper
相关产品推荐
相关产品推荐

