如何为自定义createAsyncThunk包装器添加TypeScript类型
为Redux Toolkit异步Thunk包装器添加TypeScript类型定义
我原本在JavaScript应用中使用一个Thunk包装器,现在要给它加上TypeScript类型,核心困惑是thunk和thunkAPI的类型定义。当前包装器代码如下:
export const asyncThunkHandleError = ( typePrefix: string, thunk: any, // 这里和thunkAPI的类型该怎么定义? errorMessage?: string ) => createAsyncThunk(typePrefix, async (arg: any, thunkAPI: any) => { try { // 实际调用传入的thunk return await thunk(arg, thunkAPI); } catch (error: any) { // 触发弹窗展示错误信息 thunkAPI.dispatch( openModal({ title: `Error in ${typePrefix}`, children: `${error instanceof Error ? error.message : 'Unknown error'}`, }) ); throw thunkAPI.rejectWithValue(error.response?.data || errorMessage); } });
调用方式:
// SomeComponent.tsx dispatch(getPokemons());
Thunk包装示例:
// actions/pokemons.ts const getPokemons = asyncThunkHandleError( 'pokemons/getPokemons', async (arg: any, thunkAPI: any) => { const someNetworkCall = await fetch('https://example.com'); return someNetworkCall.json(); }, 'An error occurred' );
我在Redux Toolkit源码的@reduxjs/toolkit/src/createAsyncThunk.ts里找到了BaseThunkAPI、GetThunkAPI、AsyncThunkPayloadCreator等类型,但不知道怎么正确使用它们。
解决方案
我们可以利用Redux Toolkit提供的内置类型,通过泛型为包装器实现完整的类型支持,同时保留灵活性。
1. 导入所需类型
先从Redux Toolkit导入核心类型:
import { createAsyncThunk, AsyncThunkPayloadCreator, BaseThunkAPI, AsyncThunk } from '@reduxjs/toolkit';
2. 为包装器添加泛型约束
定义三个泛型参数来覆盖核心类型场景:
Returned: 异步Thunk成功时返回的数据类型ThunkArg: 传入Thunk的参数类型(默认void表示无参数)State: 你的Redux根状态类型(需替换为项目实际类型)
然后将thunk参数指定为AsyncThunkPayloadCreator类型,thunkAPI对应BaseThunkAPI类型。
3. 完整类型化的包装器代码
import { createAsyncThunk, AsyncThunkPayloadCreator, BaseThunkAPI, AsyncThunk } from '@reduxjs/toolkit'; // 替换为你项目的Redux根状态类型 import type { RootState } from '../store'; export const asyncThunkHandleError = <Returned, ThunkArg = void>( typePrefix: string, thunk: AsyncThunkPayloadCreator<Returned, ThunkArg, {}>, errorMessage?: string ): AsyncThunk<Returned, ThunkArg, {}> => createAsyncThunk<Returned, ThunkArg, {}>(typePrefix, async (arg: ThunkArg, thunkAPI: BaseThunkAPI<RootState, any, any, any>) => { try { return await thunk(arg, thunkAPI); } catch (error) { thunkAPI.dispatch( openModal({ title: `Error in ${typePrefix}`, children: error instanceof Error ? error.message : 'Unknown error', }) ); const errorData = (error as any)?.response?.data || errorMessage; return thunkAPI.rejectWithValue(errorData); } });
4. 类型化的Thunk调用示例
现在定义Thunk时可以明确指定参数和返回值类型,TypeScript会自动进行类型校验:
// actions/pokemons.ts // 定义返回数据的类型 interface Pokemon { id: number; name: string; } interface GetPokemonsResponse { results: Pokemon[]; } const getPokemons = asyncThunkHandleError<GetPokemonsResponse, void>( 'pokemons/getPokemons', async (_, thunkAPI) => { const response = await fetch('https://pokeapi.co/api/v2/pokemon'); if (!response.ok) { throw new Error('Failed to fetch pokemons'); } return response.json(); }, 'Failed to load pokemons' );
关键类型说明
AsyncThunkPayloadCreator<Returned, ThunkArg, Options>: 描述异步Thunk核心函数的类型,包含返回值、参数和可选配置BaseThunkAPI<State, ExtraThunkArg, Dispatch, RejectValue>: 定义thunkAPI的结构,包含getState、dispatch、rejectWithValue等方法AsyncThunk<Returned, ThunkArg, Options>: 最终返回的异步Thunk类型,确保与createAsyncThunk的返回类型一致
内容的提问来源于stack exchange,提问作者Fer Toasted
相关产品推荐
相关产品推荐

