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

如何为PayloadAction设置正确的LoginError类型?

正确设置Redux Toolkit登录错误的PayloadAction类型

核心问题原因

直接给login.rejected指定PayloadAction<LoginError>报错,是因为Redux Toolkit的createAsyncThunk默认的rejected action payload类型并非你定义的LoginError——默认情况下,rejected的payload可能是unknown或原生Error对象,和自定义类型不匹配。必须通过配置thunk的泛型参数+使用rejectWithValue返回结构化错误,让TypeScript识别正确的payload类型。

分步解决代码示例

1. 定义LoginError类型

type LoginError = {
  message: string;
  status: number;
};

2. 配置createAsyncThunk的泛型参数

在创建登录异步thunk时,明确指定rejectValue的类型为LoginError,同时在异步逻辑中用rejectWithValue返回符合结构的错误数据,而非直接抛出原生Error:

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

// 假设登录成功返回的用户类型
type User = {
  id: string;
  username: string;
};

export const login = createAsyncThunk<
  User, // 登录成功时的返回类型
  { username: string; password: string }, // 登录参数类型
  { rejectValue: LoginError } // 明确rejected时的payload类型
>('auth/login', async (credentials, { rejectWithValue }) => {
  try {
    const response = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(credentials),
    });

    if (!response.ok) {
      const errorRes = await response.json();
      // 用rejectWithValue返回符合LoginError结构的错误
      return rejectWithValue({
        message: errorRes.message || '登录失败',
        status: response.status,
      });
    }

    return response.json();
  } catch (err) {
    // 处理网络等异常,同样返回结构化错误
    return rejectWithValue({
      message: '网络连接异常',
      status: 0,
    });
  }
});

3. 在slice中处理rejected action

此时login.rejected的payload会自动推导为LoginError类型(可能为undefined,需做兜底处理):

const authSlice = createSlice({
  name: 'auth',
  initialState: {
    user: null as User | null,
    error: null as LoginError | null,
    loading: false,
  },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(login.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(login.rejected, (state, action: PayloadAction<LoginError | undefined>) => {
        state.loading = false;
        // 这里action.payload已正确识别为LoginError类型
        state.error = action.payload || { message: '未知错误', status: 0 };
      })
      .addCase(login.fulfilled, (state, action) => {
        state.loading = false;
        state.user = action.payload;
        state.error = null;
      });
  },
});

export const authReducer = authSlice.reducer;

关键注意点

  • 必须使用rejectWithValue返回错误:直接throw new Error()会导致action.payload为undefined,错误信息会放在action.error中,无法匹配自定义的LoginError类型。
  • 泛型参数不可省略:只有在createAsyncThunk的泛型中指定rejectValue: LoginError,TypeScript才能正确推导rejected action的payload类型。

内容的提问来源于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.04 19:50:30