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

Redux createSlice TypeScript类型错误修复求助

Redux Toolkit createSlice TypeScript类型错误修复方案

问题描述

使用Redux Toolkit的createSlice时遇到TypeScript类型错误,核心代码如下:

import { Conversation } from "@/types/conversation";
import { PayloadAction, createSlice } from "@reduxjs/toolkit";

const initialState: Conversation | null = null;

export const conversationSlice = createSlice({
  name: "conversation",
  initialState,
  reducers: {
    setConversation: ( // type error
      state: Conversation | null,
      action: PayloadAction<Conversation>
    ) => {
      state = action.payload;
      return state;
    },
  },
});

export const { setConversation } = conversationSlice.actions;
export default conversationSlice.reducer;

收到的错误信息:

Type '(state: Conversation | null, action: PayloadAction<Conversation>) => Conversation' is not assignable to type 'CaseReducer<null, { payload: any; type: string; }> | CaseReducerWithPrepare<null, PayloadAction<any, string, any, any>>'.
  Type '(state: Conversation | null, action: PayloadAction<Conversation>) => Conversation' is not assignable to type 'CaseReducer<null, { payload: any; type: string; }>'.
    Type 'Conversation' is not assignable to type 'void'.ts(2322)

已知createSlice底层基于Immer实现:

  • 移除return语句后类型错误消失,但reducer无法正常更新状态
  • 保留return语句时功能正常,但存在类型错误
  • 尝试使用Draft类型标注state仍报错:
import { Draft, PayloadAction, createSlice } from "@reduxjs/toolkit";

interface Conversation {
  any_data: string[];
}
const initialState: Conversation | null = null;

export const conversationSlice = createSlice({
  name: "conversation",
  initialState,
  reducers: {
    setConversation: (
      // type error
      state: Draft<Conversation | null>,
      action: PayloadAction<Conversation>
    ) => action.payload,
  },
});

export const { setConversation } = conversationSlice.actions;
export default conversationSlice.reducer;

修复方案

方法1:让Redux Toolkit自动推断状态类型

不要手动指定state的类型,让Redux Toolkit根据initialState自动推断,直接返回新状态即可:

import { Conversation } from "@/types/conversation";
import { PayloadAction, createSlice } from "@reduxjs/toolkit";

const initialState: Conversation | null = null;

export const conversationSlice = createSlice({
  name: "conversation",
  initialState,
  reducers: {
    setConversation: (state, action: PayloadAction<Conversation>) => {
      return action.payload;
    },
  },
});

export const { setConversation } = conversationSlice.actions;
export default conversationSlice.reducer;

方法2:显式指定Slice泛型参数

如果需要更明确的类型控制,可给createSlice指定泛型,明确状态类型和reducer的返回值类型:

import { Conversation } from "@/types/conversation";
import { PayloadAction, createSlice } from "@reduxjs/toolkit";

type ConversationState = Conversation | null;
const initialState: ConversationState = null;

export const conversationSlice = createSlice<ConversationState, {
  setConversation: (state: ConversationState, action: PayloadAction<Conversation>) => ConversationState;
}>({
  name: "conversation",
  initialState,
  reducers: {
    setConversation: (state, action) => {
      return action.payload;
    },
  },
});

export const { setConversation } = conversationSlice.actions;
export default conversationSlice.reducer;

错误原因解析

  1. 手动指定state: Conversation | null时,TypeScript会要求reducer返回值与初始状态类型完全匹配,但返回的Conversation与Conversation | null存在类型差异,加上Immer的内部类型机制,导致冲突报错。
  2. 使用Draft<Conversation | null>标注state时,返回的原始Conversation类型无法与Immer的包装Draft类型兼容,因此报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:33:19