TypeScript+Redux Toolkit中WritableDraft类型不兼容问题求助
问题:Redux Toolkit中WritableDraft与自定义类型不兼容错误
问题背景
在React+TypeScript项目中使用Redux Toolkit开发待办应用,定义了包含Comment数组的嵌套ToDo状态,但在编写slice的reducer时出现类型不兼容错误:
- 添加ToDo时,
state.push(action.payload)抛出ToDo无法赋值给WritableDraft<ToDo>的错误 - 给现有ToDo添加Comment时,
toDo.comments.push(action.payload.comment)抛出Comment无法赋值给WritableDraft<Comment>的错误,且强制类型转换无法解决
自定义类型定义
Comment.ts
export interface Comment { id: number; comment: string; }
ToDo.ts
export interface ToDo { id: number; title: string; description: string; comments: Array<Comment>; }
Slice代码及错误
初始Slice代码:
export const toDoSlice = createSlice({ name: 'toDoSlice', initialState: [] as Array<ToDo>, reducers: { addToDo: (state, action: PayloadAction<ToDo> ) => { state.push(action.payload); }, addComment: (state, action: PayloadAction<{toDoId: number, comment: Comment}>) => { const toDo = state.find(toDo => toDo.id === action.payload.toDoId); if (toDo) { toDo.comments.push(action.payload.comment); } } } });
核心报错信息:
Argument of type 'Comment' is not assignable to parameter of type 'WritableDraft<Comment>'. Type 'Comment' is missing the following properties from type 'WritableDraft<Comment>': data, length, ownerDocument, appendData, and 59 more.
项目依赖版本:
"dependencies": { "@reduxjs/toolkit": "^1.9.0", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^13.0.0", "@testing-library/user-event": "^13.2.1", "@types/jest": "^27.0.1", "@types/node": "^16.7.13", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.4.3", "react-scripts": "5.0.1", "typescript": "^4.4.2", "web-vitals": "^2.1.0" },
解决方案
1. 解决类型命名冲突(核心原因)
错误根源是自定义的Comment接口与浏览器DOM原生的Comment类型(代表DOM注释节点)重名,导致TypeScript混淆了两个类型,进而在Immer(Redux Toolkit内置的不可变更新库)处理状态时,错误地将自定义类型与DOM类型进行匹配。
解决步骤:
- 重命名自定义的
Comment接口,避免与DOM类型冲突 - 更新所有引用该类型的代码
修改后的Comment.ts:
export interface TodoComment { id: number; comment: string; }
修改后的ToDo.ts:
import { TodoComment } from './Comment'; export interface ToDo { id: number; title: string; description: string; comments: Array<TodoComment>; }
修改后的Slice代码:
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { ToDo, TodoComment } from './types'; // 根据实际路径调整 export const toDoSlice = createSlice({ name: 'toDoSlice', initialState: [] as ToDo[], reducers: { addToDo: (state, action: PayloadAction<ToDo>) => { state.push(action.payload); }, addComment: (state, action: PayloadAction<{toDoId: number, comment: TodoComment}>) => { const toDo = state.find(todo => todo.id === action.payload.toDoId); if (toDo) { toDo.comments.push(action.payload.comment); } } } });
2. 可选:升级TypeScript版本
当前使用的TypeScript 4.4.2版本较旧,与Redux Toolkit 1.9.0的兼容性虽无问题,但升级到4.9及以上版本可以获得更好的类型推断能力,减少类似的类型混淆问题。
3. 避免强制类型转换
之前使用的as WritableDraft<ToDo>强制转换只是临时掩盖问题,并未解决根本冲突,建议移除这类转换,通过正确的类型定义解决问题。
内容的提问来源于stack exchange,提问作者AdmiJW
相关产品推荐
相关产品推荐

