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

如何为自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 01:45:42