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

使用Flow为Redux action creators做类型定义时如何实现DRY?

如何精简类型定义,避免重复派发函数的类型

当然可以!你完全能通过提取共享类型的方式来避免这种重复定义的麻烦,核心就是把setProjectSubNavigation的方法类型从actions模块中抽出来复用,不用在组件props里重新写一遍。我分TS和JS(带JSDoc)两种场景给你举例:

TypeScript 场景

第一步:在actions模块中导出共享类型

先把setProjectSubNavigation的方法签名单独抽成类型导出,比如你的actions.ts可以这么写:

// actions.ts
// 先定义方法的参数类型(如果有参数的话)
export type SetProjectSubNavigationParams = {
  navItem: string;
  // 其他需要的参数...
};

// 导出该方法的完整类型
export type SetProjectSubNavigationAction = (
  params: SetProjectSubNavigationParams
) => void;

// 实际的action creator,直接用上面的类型约束
export const setProjectSubNavigation: SetProjectSubNavigationAction = (params) => {
  return {
    type: 'SET_PROJECT_SUB_NAV',
    payload: params,
  };
};

第二步:在组件中复用该类型

然后在component.tsx里,直接导入这个类型来定义props,不用重复写类型结构:

// component.tsx
import type { SetProjectSubNavigationAction } from './actions';

// 组件Props类型,直接复用已定义好的类型
type ComponentProps = {
  setProjectSubNavigation: SetProjectSubNavigationAction;
  // 其他组件props...
};

export const MyComponent = ({ setProjectSubNavigation }: ComponentProps) => {
  const handleNavClick = () => {
    setProjectSubNavigation({ navItem: 'analytics' });
  };

  return <button onClick={handleNavClick}>切换子导航</button>;
};

进阶:Redux 全局复用Dispatch类型

如果你用Redux这类状态管理库,还可以直接导出全局的Dispatch类型,一次性覆盖所有action的类型,不用单独导出每个action的类型:

// store.ts
import { configureStore } from '@reduxjs/toolkit';
import projectReducer from './projectSlice';

export const store = configureStore({
  reducer: {
    project: projectReducer,
  },
});

// 导出自动推断的Dispatch类型,包含所有action的类型信息
export type AppDispatch = typeof store.dispatch;

然后组件里直接用这个AppDispatch:

// component.tsx
import type { AppDispatch } from './store';
import { setProjectSubNavigation } from './actions';

type ComponentProps = {
  dispatch: AppDispatch;
};

export const MyComponent = ({ dispatch }: ComponentProps) => {
  const handleNavClick = () => {
    // 这里dispatch会自动提示setProjectSubNavigation的参数类型,完全不用手动定义
    dispatch(setProjectSubNavigation({ navItem: 'analytics' }));
  };

  return <button onClick={handleNavClick}>切换子导航</button>;
};

JavaScript + JSDoc 场景

如果你的项目是JS但用JSDoc做类型提示,同样可以提取共享类型:

// actions.js
/**
 * @typedef {Object} SetProjectSubNavigationParams
 * @property {string} navItem
 */

/**
 * @typedef {(params: SetProjectSubNavigationParams) => void} SetProjectSubNavigationAction
 */

/** @type {SetProjectSubNavigationAction} */
export const setProjectSubNavigation = (params) => {
  // action逻辑
};

然后组件里通过import()引用这个类型:

// component.js
/**
 * @typedef {Object} ComponentProps
 * @property {import('./actions').SetProjectSubNavigationAction} setProjectSubNavigation
 */

/**
 * @param {ComponentProps} props
 */
export const MyComponent = ({ setProjectSubNavigation }) => {
  const handleNavClick = () => {
    setProjectSubNavigation({ navItem: 'analytics' });
  };

  return <button onClick={handleNavClick}>切换子导航</button>;
};

总的来说,核心思路就是把重复的类型逻辑抽成可复用的模块级类型,不管是TS还是JS+JSDoc,都能彻底避免在多个地方重复定义同一个方法的类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:27:13