TS下Context API的useReducer state类型推断为any解决方法
React Context + useReducer 状态类型推断为any的修复方案
核心问题根源是globalReducer未做明确类型标注,TypeScript无法从reducer逻辑反向推导状态类型,即使defaultState标注了StateInterface,useReducer的类型推导优先级会以传入的reducer类型为准,最终导致state被推断为any。
具体配置步骤
- 定义基础类型与类型安全的reducer
首先明确状态类型、Action的判别联合类型,再给reducer的入参、返回值做严格类型标注,从源头让TS识别reducer处理的状态结构:
// 全局状态类型 interface StateInterface { data: boolean; } // 所有合法的action类型,用判别联合约束type和payload的对应关系 type GlobalReducerAction = | { type: 'SET_DATA'; payload: boolean } // 后续新增action直接在联合类型里追加即可 // 标注reducer的state入参、action入参、返回值类型 const globalReducer = ( state: StateInterface, action: GlobalReducerAction ): StateInterface => { switch (action.type) { case 'SET_DATA': return { ...state, data: action.payload }; default: // default分支必须返回原state,避免返回值类型不匹配 return state; } }; export const defaultState: StateInterface = { data: false, };- 定义基础类型与类型安全的reducer
- 补全Context的完整类型定义
多数场景下Context需要同时对外暴露state和dispatch,不要直接用defaultState作为Context的类型,要单独定义Context承载的完整结构:
import { createContext, Dispatch } from 'react'; // 定义Context承载的全部内容类型 interface GlobalContextValue { state: StateInterface; dispatch: Dispatch<GlobalReducerAction>; } // 初始化Context时用类型断言做兜底,不需要写冗余的默认dispatch实现 export const globalContext = createContext<GlobalContextValue>( {} as GlobalContextValue );- 补全Context的完整类型定义
- 修正Provider中的传值逻辑
完成前两步后,useReducer返回的state会被自动推导为StateInterface类型,和defaultState类型完全一致,不会再出现any:
import { useReducer, FC } from 'react'; const GlobalProvider: FC<{ children: React.ReactNode }> = ({ children }) => { // 此处state会被TS自动识别为StateInterface类型 const [state, dispatch] = useReducer(globalReducer, defaultState); return ( <globalContext.Provider value={{ state, dispatch }}> {children} </globalContext.Provider> ); }; export default GlobalProvider;- 修正Provider中的传值逻辑
校验方式
把鼠标悬停在Provider内的state变量上,TypeScript会提示其类型为StateInterface,后续在组件中消费Context时,state的属性也会有完整的类型提示。
注意:不需要给useReducer手动追加冗余的泛型参数,只要reducer的类型标注正确,TS会自动完成类型推导,手动指定泛型反而可能掩盖类型不匹配的问题。
内容的提问来源于stack exchange,提问作者Richardson
相关产品推荐
相关产品推荐

