React+TypeScript+Redux中访问state.authorize报属性不存在问题求解
React + TypeScript Redux 状态类型推导报错问题
场景说明
在React结合TypeScript开发的项目中,需要通过Redux读取全局状态,按照Redux官方静态类型规范,需要从reducer定义处导出统一的RootState类型,供useSelector等hook使用。
涉及的业务代码如下:
Component.tsx
import { RootState } from 'src/store/reducers' const authorize = useSelector((state: RootState) => { return { authorize: state.authorize } })
rootReducer.tsx
export const rootReducer = (history: any) => combineReducers({ authorize: authorizeReducer, router: connectRouter(history) }) export type RootState = ReturnType<typeof rootReducer>
报错情况
已经在combineReducers的配置对象中明确声明了authorize属性,运行时抛出类型错误:
Property 'authorize' does not exist on type 'Reducer<{ authorize: Map<unknown, unknown>; router: RouterState; }, AnyAction>'
问题根因
rootReducer本身是一个接收history参数的函数,不是最终的根状态对象,也不是可直接作为类型使用的静态结构:
- 当前写法中
ReturnType<typeof rootReducer>拿到的是这个函数的返回值,也就是combineReducers生成的Reducer函数本身 - 把这个Reducer函数直接当成
RootState的类型,自然没法从函数上直接访问到内部持有的authorize状态属性 - 实际需要的状态结构,是这个Reducer函数的第一个入参类型,而不是函数本身
解决方案
调整RootState的类型推导逻辑,从Reducer函数的入参中提取真正的状态结构:
- 先通过
ReturnType拿到rootReducer返回的合并后Reducer类型 - 再提取这个合并后Reducer第一个参数(也就是全局根状态对象)的类型,作为最终的
RootState
对应的修改代码:
// rootReducer.tsx 中修正后的类型定义 export const rootReducer = (history: any) => combineReducers({ authorize: authorizeReducer, router: connectRouter(history) }) // 原错误写法:直接把函数返回的Reducer本身当成RootState // export type RootState = ReturnType<typeof rootReducer> // 修正写法:从Reducer的入参中提取状态结构 type CombinedRootReducer = ReturnType<typeof rootReducer> export type RootState = Parameters<CombinedRootReducer>[0]
优化建议
如果后续不需要动态传入reducer参数,也可以把纯静态的reducer配置抽离出来,减少类型推导的绕路:
// 抽离无外部依赖的静态reducer配置 const staticReducers = { authorize: authorizeReducer } // 动态创建绑定了路由history的根reducer export const createRootReducer = (history: any) => combineReducers({ ...staticReducers, router: connectRouter(history) }) // 类型定义同样可以从动态创建的reducer中提取状态结构 type CombinedReducer = ReturnType<typeof createRootReducer> export type RootState = Parameters<CombinedReducer>[0]
内容的提问来源于stack exchange,提问作者wisdomtoothman
相关产品推荐
相关产品推荐

