TypeScript中React action/reducer模式下如何更优雅标注data类型?
优化方案
可以通过泛型工具提取对应类型的Action,让每个处理函数的入参自动匹配对应类型,无需手动添加类型守卫,也不需要switch语句,实现代码如下:
// 示例State类型,可根据实际业务调整 type State = { nums: number[] }; export type Action = { type: "DO_SOMETHING", data: { num: number } } | { type: "DO_SOMETHING_ELSE", data: { nums: number[] } }; // 工具泛型:根据type值从Action联合类型中提取对应完整Action项 type ExtractActionByType<T extends Action['type']> = Extract<Action, { type: T }>; // 重构Actions映射类型,每个处理函数只接收对应type的action type Actions = { [T in Action['type']]: (state: State, action: ExtractActionByType<T>) => State; }; // 现在每个处理函数的action类型自动匹配,无需额外类型判断 const actions: Actions = { DO_SOMETHING: (state, action) => { return { nums: [action.data.num] }; }, DO_SOMETHING_ELSE: (state, action) => { return { nums: action.data.nums }; } }; // 配套类型安全的reducer实现 function reducer(state: State, action: Action): State { return actions[action.type](state, action as never); }
方案说明
- 新增action类型时仅需更新
Action联合类型定义,TypeScript会自动校验actions对象中是否存在对应类型的处理函数,避免漏写逻辑。 - 所有处理函数的
action参数类型自动推导,无需手动编写类型守卫代码,比原生switch写法更简洁,类型安全性完全一致。 - reducer中的
as never是对TypeScript类型系统的合理妥协,由于TS暂时无法自动推导映射函数的入参与传入action的类型匹配关系,该写法完全类型安全,不会引入运行时风险。
内容的提问来源于stack exchange,提问作者ChevCast
相关产品推荐
相关产品推荐

