TypeScript下Redux自定义API中间件的dispatch返回类型如何定义
Redux 自定义API中间件Dispatch返回值TypeScript定义方案
问题根源
Redux 默认的 Dispatch 类型定义是为同步普通action设计的,约定dispatch(action)的返回值就是你传入的action本身,所以TypeScript会认为你传入fetchUsers()返回的普通对象,不是Promise,自然会提示await没有效果,也不知道中间件实际会返回用户列表的Promise。
1. 定义带返回值关联的异步Action类型
首先给你的异步action构造器加泛型关联,将action和它执行后返回的结果类型绑定:
// 定义通用异步Action类型,泛型参数T为该action执行后返回的结果类型 type AsyncAction<T = unknown> = { type: string // 可扩展你中间件需要的其他字段,如请求url、参数等 } // 示例:fetchUsers的返回值关联User[]类型 const fetchUsers = (): AsyncAction<User[]> => ({ type: 'FETCH_USERS' })
2. 扩展Redux Dispatch类型
覆盖默认的Dispatch类型定义,让它支持异步返回:
import type { Dispatch as DefaultDispatch } from 'redux' // 重载Dispatch类型:当入参是AsyncAction时,返回对应泛型类型的Promise type AppDispatch = DefaultDispatch & <T>(action: AsyncAction<T>) => Promise<T>
3. 适配useDispatch
有两种方式可以让useDispatch识别扩展后的类型:
- 方案1:封装自定义hooks(推荐,不用每次调用重复指定类型)
import { useDispatch as useOriginalDispatch } from 'react-redux' export const useDispatch = () => useOriginalDispatch<AppDispatch>()
- 方案2:每次调用时手动指定泛型
const dispatch = useDispatch<AppDispatch>()
4. (可选)调整中间件返回值
如果你需要dispatch直接返回接口数据而不是完整的结果action,调整中间件的返回逻辑:
const apiMiddleware = store => next => async action => { next(action) // 你的接口请求逻辑 const { data } = await axios.get('/your/api/path') next({ type: 'FETCH_USERS_RESULTS', data }) // 直接返回数据,和前面的AsyncAction泛型对应 return data }
配置完成后就可以直接使用,不需要额外类型断言:
const dispatch = useDispatch() // users自动推导为User[]类型,不会再出现await无效的报错 const users = await dispatch(fetchUsers())
内容的提问来源于stack exchange,提问作者Ali Kazemkhanloo
相关产品推荐
相关产品推荐

