Typescript中如何给Redux-Toolkit createAsyncThunk的rejected payload指定string类型
环境
- Redux-Toolkit
- React
- Typescript
- GraphQL
背景
我使用redux和redux-toolkit做本地状态管理,查阅redux-toolkit官方文档可知,可以通过其提供的createAsyncThunk()方法派发thunk异步action,该方法会自动派发pending、fulfilled、rejected三种类型的action。
异步任务执行失败时,thunk会派发rejected类型的action,默认情况下action.error为SerializedError类型,我们可以通过rejectWithValue()方法自定义错误返回结果,示例代码如下:
const fetchAdminPassword = createAsyncThunk('adminPassword/fetch', async (_, { rejectWithValue }) => { try { const result = await client.query<{adminPassword: string}>({ query: FETCH_ADMIN_PASSWORD }); const { data: { adminPassword } } = result; return adminPassword; } catch (err) { rejectWithValue("Error!!"); } }); builder.addCase(fetchAdminPassword.rejected, (state, action) => { state.fetchError = action.payload; state.fetchPending = false; })
问题
上述示例代码中,rejected回调内的action.payload类型为unknown,如何将其类型修改为string?
解决方案
要为rejected状态的action.payload指定string类型,最标准的做法是给createAsyncThunk传入泛型参数,明确定义rejectWithValue的返回值类型:
createAsyncThunk支持传入三个泛型参数,依次为:- 异步函数成功返回值的类型
- thunk接收的入参类型(你当前的代码没有入参,所以填
void) - 配置项类型,这里只需要指定
rejectValue为string即可
- 注意你当前的示例代码有个疏漏:
catch分支里必须return rejectWithValue("Error!!"),否则返回值为undefined,类型匹配也会异常。
修改后的完整代码如下:
// 给createAsyncThunk传入泛型定义 const fetchAdminPassword = createAsyncThunk<string, void, { rejectValue: string }>( 'adminPassword/fetch', async (_, { rejectWithValue }) => { try { const result = await client.query<{adminPassword: string}>({ query: FETCH_ADMIN_PASSWORD }); const { data: { adminPassword } } = result; return adminPassword; } catch (err) { // 这里必须加return return rejectWithValue("Error!!"); } } ); builder.addCase(fetchAdminPassword.rejected, (state, action) => { // 此时action.payload的类型会自动推导为string | undefined state.fetchError = action.payload; state.fetchPending = false; })
如果你不想修改createAsyncThunk的定义,也可以在addCase回调中临时使用类型断言:
builder.addCase(fetchAdminPassword.rejected, (state, action) => { state.fetchError = action.payload as string; state.fetchPending = false; })
不过这种方法没有编译期类型校验,更推荐使用泛型定义的方案。
内容的提问来源于stack exchange,提问作者Byeongin Yoon
相关产品推荐
相关产品推荐

