使用TypeScript/RTK时如何定义rejected场景下payload对象的类型
问题解决方案
你遇到的报错根源有两个:
- 没有给
createAsyncThunk声明rejectValue的类型,TS默认将rejected状态的payload推导为unknown - 你在
rejectWithValue里传的是字符串类型的error.message,但reducer里却尝试取payload.message,属于逻辑错误,字符串本身没有message属性
步骤1:给两个createAsyncThunk添加完整泛型声明
createAsyncThunk支持传入三个泛型参数,分别为:
- 第1位:异步请求成功后的返回值类型
- 第2位:thunk的入参类型
- 第3位:配置项,用来声明
rejectValue的类型
修改后的thunk代码如下:
// 修改forgotPasswordRequest的泛型声明 export const forgotPasswordRequest = createAsyncThunk< null, // 成功后返回null ForgotPasswordRequestProps, // 入参类型 { rejectValue: string } // rejectWithValue返回的值为string类型 >( 'auth/forgotPasswordRequest', async (data, { rejectWithValue }) => { const { email } = data; try { const response = await Axios.anon.post(`/v1/auth/forgot-password`, { email }); if (response.status === 204) return null; } catch (error) { if (error instanceof Error) return rejectWithValue(error.message); // 统一兜底返回错误信息,避免返回undefined return rejectWithValue('未知错误'); } } ); // 同理修改forgotPasswordSet的泛型声明 export const forgotPasswordSet = createAsyncThunk< null, ForgotPasswordSetProps, { rejectValue: string } >( 'auth/verifyEmailSet', async (data, { rejectWithValue }) => { const { query, password } = data; try { const response = await Axios.anon.post(`/v1/auth/reset-password?token=${query}`, { password }); if (response.status === 204) return null; } catch (error) { if (error instanceof Error) return rejectWithValue(error.message); return rejectWithValue('未知错误'); } } );
步骤2:修改rejected分支的逻辑
添加泛型后TS可以自动推导payload为string | undefined类型,不需要额外手动标注action类型,同时修正取值逻辑:
.addCase( forgotPasswordRequest.rejected, (state, action) => { state.status.isPending = false; state.status.isError = true; // 直接用payload,加兜底避免undefined state.status.errorMessage = action.payload ?? '请求失败'; } ) .addCase( forgotPasswordSet.rejected, (state, action) => { state.status.isPending = false; state.status.isError = true; state.status.errorMessage = action.payload ?? '请求失败'; } )
可选手动标注方案
如果你需要明确手动标注action类型,可以导入PayloadAction后指定类型:
import type { PayloadAction } from '@reduxjs/toolkit'; .addCase( forgotPasswordRequest.rejected, (state, action: PayloadAction<string | undefined>) => { state.status.errorMessage = action.payload ?? '请求失败'; } )
修改完成后所有类型错误都会消失,逻辑也符合你实际的返回值规则。
内容的提问来源于stack exchange,提问作者benji
相关产品推荐
相关产品推荐

