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

使用TypeScript编写Redux Slice时Reducer报never类型错误排查

Redux Slice泛型Reducer类型错误解决方案

问题根源

你遇到的never类型错误,是因为createSlice无法自动推断泛型Reducer的具体类型。单独测试setState函数时,TypeScript能通过传入的参数推断出泛型T的类型,但把这个泛型函数直接传入createSlice的reducers对象时,TypeScript无法将T绑定到IFeatureState,导致payload的类型被解析为never。

解决方法

方法一:为泛型Reducer绑定具体类型

把泛型的setState函数转换为针对IFeatureState的具体函数,让TypeScript明确知道payload的类型:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

// 原有的StatePayload类型和setState泛型函数
type StatePayload<T> = {
  [K in keyof T]: {
    propName: K;
    value: T[K];
  };
}[keyof T];

function setState<T>(state: T, { payload }: PayloadAction<StatePayload<T>>) {
  state[payload.propName] = payload.value;
}

// 创建绑定了IFeatureState类型的具体reducer函数
const setStateForFeature = (
  state: IFeatureState,
  action: PayloadAction<StatePayload<IFeatureState>>
) => setState(state, action);

// 创建Slice时使用这个具体函数
const appSlice = createSlice({
  name: 'app',
  initialState,
  reducers: {
    setState: setStateForFeature,
  },
});

// 此时调用action creator就不会报错了
appSlice.actions.setState({ propName: 'content', value: 'test' });

方法二:直接在createSlice内定义类型明确的Reducer

放弃单独的泛型函数,直接在createSlice的reducers中编写类型明确的处理逻辑,这样TypeScript能直接推断出action的类型:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

interface IFeatureState {
  content: string;
  open: boolean;
}

const initialState: IFeatureState = {
  content: "",
  open: false,
};

// 针对当前State定义Payload类型
type FeatureStatePayload = {
  [K in keyof IFeatureState]: {
    propName: K;
    value: IFeatureState[K];
  };
}[keyof IFeatureState];

const appSlice = createSlice({
  name: 'app',
  initialState,
  reducers: {
    setState: (state, action: PayloadAction<FeatureStatePayload>) => {
      state[action.payload.propName] = action.payload.value;
    },
  },
});

// 正常调用action creator
appSlice.actions.setState({ propName: 'open', value: true });

方法三:利用Immer Draft类型优化(可选)

Redux Toolkit默认使用Immer处理状态更新,你可以利用Immer的Draft类型进一步强化类型安全:

import { createSlice, PayloadAction, Draft } from '@reduxjs/toolkit';

const appSlice = createSlice({
  name: 'app',
  initialState,
  reducers: {
    setState: (state: Draft<IFeatureState>, action: PayloadAction<FeatureStatePayload>) => {
      state[action.payload.propName] = action.payload.value;
    },
  },
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:25:17