使用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
相关产品推荐
相关产品推荐

