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

如何使用TypeScript简化Redux Thunk动作代码?

简化Redux Thunk + TypeScript代码的几个实用方案

看起来你已经在尝试精简Redux Thunk结合TypeScript的代码了,这里有几个能进一步简化的方向,从基础优化到官方推荐的工具方案都有:

1. 先优化基础类型与工具函数

消除any并复用动作类型

首先把模糊的any替换成具体类型,同时给动作类型创建别名减少重复书写:

// 给API_REQUEST动作创建类型别名,避免重复写ModalActionTypes["API_REQUEST"]
type ApiRequestAction = ModalActionTypes["API_REQUEST"];

// 定义payload的具体类型(根据你的业务场景调整,比如结合IContactForm或其他接口)
type ApiPayload = IContactForm | Record<string, unknown>;

export function apiRequestDispatcher(
  status: string,
  payload?: ApiPayload
): ApiRequestAction {
  return {
    type: "API_REQUEST",
    status, // ES6属性简写,等价于status: status
    payload, // 同样简写
  };
}

通用Thunk生成函数

如果有多个类似sendEmail的异步action,可以封装一个通用生成器,避免重复写Thunk的泛型参数:

// 提前定义全局Thunk类型,复用所有异步action
type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState, // 替换成你的根状态类型
  unknown,
  ModalActionTypes
>;

// 通用API请求Thunk生成器
function createApiThunk<Payload>(
  apiCall: (payload: Payload) => Promise<any>,
  successStatus: string,
  errorStatus: string
) {
  return (payload: Payload): AppThunk<Promise<ApiRequestAction>> => async (dispatch) => {
    try {
      const response = await apiCall(payload);
      return dispatch(apiRequestDispatcher(successStatus, response));
    } catch (error) {
      return dispatch(apiRequestDispatcher(errorStatus, error));
    }
  };
}

// 现在sendEmail可以极简定义
export const sendEmail = createApiThunk<IContactForm>(
  (details) => fetch("/api/email", { method: "POST", body: JSON.stringify(details) }),
  "EMAIL_SENT_SUCCESS",
  "EMAIL_SENT_ERROR"
);

2. 推荐使用Redux Toolkit(官方最优解)

Redux Toolkit是官方推出的简化工具,内置Redux Thunk,对TypeScript支持非常友好,能彻底消除样板代码:

用createAsyncThunk替代手动Thunk

createAsyncThunk会自动生成pending/fulfilled/rejected三种状态的action,无需手动维护status:

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

// 自动生成异步动作类型,无需手动定义字符串常量
export const sendEmail = createAsyncThunk(
  "modal/sendEmail",
  async (messageDetails: IContactForm) => {
    const response = await fetch("/api/email", {
      method: "POST",
      body: JSON.stringify(messageDetails),
    });
    return response.json(); // 返回值会作为fulfilled动作的payload
  }
);

// 用createSlice创建reducer,自动处理异步动作
const modalSlice = createSlice({
  name: "modal",
  initialState: {
    status: "idle",
    data: null,
    error: null,
  },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(sendEmail.pending, (state) => {
        state.status = "loading";
      })
      .addCase(sendEmail.fulfilled, (state, action) => {
        state.status = "success";
        state.data = action.payload;
      })
      .addCase(sendEmail.rejected, (state, action) => {
        state.status = "error";
        state.error = action.error.message;
      });
  },
});

export const modalReducer = modalSlice.reducer;

这套方案里,你不需要手动写apiRequestDispatcher,TypeScript会自动推断所有类型,代码量减少一半以上,还能避免拼写错误和类型不匹配问题。

3. 额外小技巧:用枚举管理动作类型

如果还在手动维护动作字符串,用枚举替代可以避免拼写错误:

enum ModalActionTypes {
  API_REQUEST = "API_REQUEST",
  // 其他动作类型
}

// 在dispatcher里使用枚举:
return {
  type: ModalActionTypes.API_REQUEST,
  status,
  payload,
};

内容的提问来源于stack exchange,提问作者Andrew Font

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:52:45