使用combineReducers组合多Reducer遇TypeScript state属性未知错误
Redux + TypeScript:State属性无法识别的问题解决
问题场景
我按如下方式配置Redux Store:
const rootReducer = combineReducers({ login: loginReducer, counter: counterReducer }); const store = configureStore({ reducer: rootReducer });
login切片代码:
import { createSlice } from '@reduxjs/toolkit'; const loginSlice = createSlice({ name: 'login', initialState: { isLoggedIn: false, }, reducers: { login: (state) => { state.isLoggedIn = true; }, logout: (state) => { state.isLoggedIn = false; }, }, }); export const { login, logout } = loginSlice.actions; export default loginSlice.reducer;
counter切片代码:
import { createSlice } from '@reduxjs/toolkit'; export const counterSlice = createSlice({ name: 'counter', initialState: { counterValue: 0, }, reducers: { increment: (state) => { state.counterValue += 1; }, decrement: (state) => { state.counterValue -= 1; }, incrementByAmount: (state, action) => { state.counterValue += action.payload; }, }, }); export const { increment, decrement, incrementByAmount } = counterSlice.actions; export default counterSlice.reducer;
尝试通过useSelector((state) => state.counter.counterValue)或useSelector((state) => state.login.isLoggedIn)访问状态时,出现TypeScript错误:Property 'counter' does not exist on type 'unknown';直接访问state.counterValue返回undefined。
问题原因
TypeScript无法自动推断Redux store的state结构,默认将useSelector的state参数类型设为unknown,因此访问state.counter这类属性时会触发类型错误。而直接访问state.counterValue返回undefined,是因为store的顶层state是由combineReducers定义的包含login和counter子对象的结构,counterValue属于counter子对象下的属性,必须通过层级访问。
解决方法
方法1:导出RootState类型并手动指定
在定义store的文件中,添加类型推导:
// 从store.getState的返回值推导RootState类型 export type RootState = ReturnType<typeof store.getState>;
在组件中使用useSelector时,指定state类型:
import { useSelector } from 'react-redux'; import type { RootState } from './path-to-your-store-file'; const counterValue = useSelector((state: RootState) => state.counter.counterValue); const isLoggedIn = useSelector((state: RootState) => state.login.isLoggedIn);
方法2:创建自定义Typed Selector钩子(推荐)
为了避免重复手动指定类型,创建一个自定义的useAppSelector钩子:
// 比如在src/hooks.ts文件中 import { useSelector, TypedUseSelectorHook } from 'react-redux'; import type { RootState } from './path-to-your-store-file'; export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
之后在组件中直接使用该钩子,无需再手动指定类型:
import { useAppSelector } from './hooks'; const counterValue = useAppSelector(state => state.counter.counterValue); const isLoggedIn = useAppSelector(state => state.login.isLoggedIn);
内容的提问来源于stack exchange,提问作者erol_smsr
相关产品推荐
相关产品推荐

