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

使用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'.

解决方案

核心问题分析

  1. 手动指定action: PayloadAction<AuthInterface>与login.rejected实际的action类型不匹配:login.rejected的payload是rejectWithValue返回的错误数据,而非AuthInterface类型。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:15:31