使用createReducer构建器语法时遭遇TS2769错误求助
解决Redux Toolkit中createSlice处理login.rejected时的TS2769类型错误
问题场景
使用Redux Toolkit的createSlice构建器语法编写登录状态更新reducer时,处理login.rejected的case出现TS2769类型错误,不想用any类型规避问题。
原代码
export interface AuthInterface { loading: boolean; userToken: boolean | null; error: string | null; success: boolean; } export interface AuthState { auth: AuthInterface; } const initialState: AuthState = { auth: { loading: false, userToken: null, error: null, success: false, } } export const login = createAsyncThunk( "auth/login", async (loginData: LoginData, thunkAPI: any) => { try { const { email, password } = loginData; const res = await axios.post<UserLogin>( "http://localhost:4000/login", { email: email, password: password, } ); return res.data; } catch (error) { return thunkAPI.rejectWithValue(error); } } ) export const authSlice = createSlice({ name: "auth", initialState, reducers: {}, extraReducers: (builder) => { builder.addCase(login.fulfilled, (state, action: PayloadAction<AuthInterface>) => { state.auth.loading = false; state.auth.success = true; state.auth.error = null; }) // 此代码块出现TS2769错误 builder.addCase(login.rejected, (state, action:PayloadAction<AuthInterface>) => { state.auth.loading = false; state.auth.success = false; state.auth.error = action.payload.error }) } });
错误信息
TS2769: No overload matches this call. Overload 1 of 2, '(actionCreator: AsyncThunkRejectedActionCreator<LoginData, AsyncThunkConfig>, reducer: CaseReducer<AuthState, PayloadAction<...>>): ActionReducerMapBuilder<...>', gave the following error. Argument of type '(state: WritableDraft<AuthState>, action: { payload: AuthInterface; type: string; }) => void' is not assignable to parameter of type 'CaseReducer<AuthState, PayloadAction<unknown, string, { arg: LoginData; requestId: string; requestStatus: "rejected"; aborted: boolean; condition: boolean; } & ({ rejectedWithValue: true; } | ({ ...; } & {})), SerializedError>>'. Types of parameters 'action' and 'action' are incompatible. Type 'PayloadAction<unknown, string, { arg: LoginData; requestId: string; requestStatus: "rejected"; aborted: boolean; condition: boolean; } & ({ rejectedWithValue: true; } | ({ rejectedWithValue: false; } & {})), SerializedError>' is not assignable to type '{ payload: AuthInterface; type: string; }'. Types of property 'payload' are incompatible. Type 'unknown' is not assignable to type 'AuthInterface'. Overload 2 of 2, '(type: string, reducer: CaseReducer<AuthState, { payload: AuthInterface; type: string; }>): ActionReducerMapBuilder<AuthState>', gave the following error. Argument of type 'AsyncThunkRejectedActionCreator<LoginData, AsyncThunkConfig>' is not assignable to parameter of type 'string'.
解决方案
核心问题分析
- 手动指定
action: PayloadAction<AuthInterface>与login.rejected实际的action类型不匹配:login.rejected的payload是rejectWithValue返回的错误数据,而非AuthInterface类型。 thunkAPI: any导致TypeScript无法推导rejectWithValue的返回类型,必须明确指定错误数据的类型。
具体修改步骤
1. 定义错误响应的类型接口
// 后端返回的错误响应结构,根据实际情况调整 interface LoginErrorResponse { error: string; }
2. 修正createAsyncThunk的类型定义
移除thunkAPI: any,明确指定fulfilled、参数、reject的类型,同时正确处理axios错误:
import { AxiosError } from 'axios'; export const login = createAsyncThunk< UserLogin, // fulfilled状态下的payload类型 LoginData, // 传入的参数类型 { rejectValue: LoginErrorResponse } // rejected状态下的payload类型 >( "auth/login", async (loginData, thunkAPI) => { try { const { email, password } = loginData; const res = await axios.post<UserLogin>( "http://localhost:4000/login", { email, password } ); return res.data; } catch (error) { // 断言错误为axios的AxiosError类型,获取响应中的错误数据 const axiosError = error as AxiosError<LoginErrorResponse>; // 兜底处理,避免无响应数据的情况 return thunkAPI.rejectWithValue( axiosError.response?.data || { error: '登录失败,请稍后重试' } ); } } );
3. 移除手动指定的action类型,让Redux Toolkit自动推导
export const authSlice = createSlice({ name: "auth", initialState, reducers: {}, extraReducers: (builder) => { builder.addCase(login.fulfilled, (state, action) => { state.auth.loading = false; state.auth.success = true; state.auth.error = null; // 这里可以根据action.payload(UserLogin类型)设置userToken // state.auth.userToken = action.payload.token; }); builder.addCase(login.rejected, (state, action) => { state.auth.loading = false; state.auth.success = false; // action.payload现在是LoginErrorResponse类型,可安全访问error字段 state.auth.error = action.payload?.error || '未知错误'; }); } });
说明
- Redux Toolkit会自动根据
createAsyncThunk的泛型定义推导fulfilled和rejected的action类型,无需手动指定PayloadAction。 - 明确错误类型后,TypeScript可以提供完整的类型检查,避免使用
any带来的类型安全问题。
内容的提问来源于stack exchange,提问作者code_learner93
相关产品推荐
相关产品推荐

