使用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
相关产品推荐
相关产品推荐

