如何定义支持普通Action与Thunk的Redux Dispatch函数类型?
你好!这个问题在Redux类型定义里挺典型的,我来一步步帮你搞定它~
首先,你的核心需求是让DispatchFunc既能接受普通Action(比如foo()的返回值),又能接受Thunk函数(比如bar()返回的Promise),同时还要保证返回值类型正确。我们可以分两步来实现:
第一步:提取所有Action Creator的返回值联合类型
首先我们需要把AppActionCreators里所有方法的返回值提取出来,组成一个联合类型。用TypeScript的keyof和ReturnType就能轻松做到:
// 提取AppActionCreators中所有方法的返回值,得到普通Action和Promise<string>的联合类型 type AppActionUnion = ReturnType<AppActionCreators[keyof AppActionCreators]>;
这里keyof AppActionCreators会拿到foo和bar这两个属性名,AppActionCreators[keyof AppActionCreators]就是这两个方法的类型,再用ReturnType<>就能得到它们的返回值类型的联合。
第二步:定义支持Thunk的Dispatch类型
Redux默认的Dispatch类型只能处理普通Action,要支持Thunk的话,我们需要用到redux-thunk提供的ThunkDispatch类型(如果你还没装redux-thunk的话,得先安装它)。我们把ThunkDispatch和普通Dispatch交叉起来,就能得到同时支持两种场景的类型:
import { Dispatch } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; // 替换成你实际的State类型,如果没有具体类型可以用{} type AppState = {}; export type DispatchFunc = ThunkDispatch<AppState, {}, AppActionUnion> & Dispatch<AppActionUnion>;
验证效果
现在你就可以正常使用这个DispatchFunc了,类型检查完全能满足你的需求:
const dispatch: DispatchFunc = ...; // 普通Action,类型正确 dispatch(foo()); // Thunk Action,返回Promise<string>,可以直接调用.then() dispatch(bar()).then((str) => { console.log(str); // str的类型是string,完全正确 });
补充说明
如果你用的是@reduxjs/toolkit(现在推荐的Redux写法),其实它已经内置了Thunk的类型支持,你甚至可以不用手动定义DispatchFunc,直接从store里获取的dispatch就已经是正确的类型了。但如果是手动配置的Redux,上面的写法就完全适用。
备注:内容来源于stack exchange,提问作者SudoPlz

