使用Redux connect创建TypeScript HOC时泛型参数报错求助
I see exactly where you're stuck here—TypeScript is clashing with your custom Redux store state because connect is defaulting to Redux's built-in DefaultRootState instead of your StoreState interface. Let's break down the problem and fix it step by step.
Why the Error Occurs
The error message tells us DefaultRootState (Redux's empty default state type) doesn't have the comments and auth properties defined in your StoreState. When you use connect without explicitly declaring your store's state type, TypeScript assumes you're working with that empty default, which conflicts with your mapStateToProps function that expects your full StoreState.
Solution 1: Explicitly Define the Store State in connect Generics
The connect function accepts four generic parameters in this exact order:
- Props injected by
mapStateToProps - Props injected by
mapDispatchToProps(empty in your case) - Props passed directly to the HOC (
OwnProps) - Your custom store state type
You were missing the fourth parameter, so TypeScript fell back to DefaultRootState. Update your connect call to include your StoreState:
return connect<Props, {}, OwnProps, StoreState>(mapStateToProps)(ComposedComponent)
This explicitly tells TypeScript what state structure mapStateToProps should expect, eliminating the type mismatch.
Solution 2: Globally Configure Your Root State (Recommended for Projects)
If you don't want to repeat the state type in every connect call, you can override the default DefaultRootState globally. Create a redux.d.ts file in your project's src folder with this code:
import { StoreState } from '../reducers'; // Adjust the import path to match your project declare module 'react-redux' { interface DefaultRootState extends StoreState {} }
Now TypeScript will automatically use your StoreState as the default root state for all connect calls across your project—no more manual generic typing needed.
Bonus: Refine Your HOC's Type Safety
Your current HOC has a small type issue: React.ComponentType<typeof ChildComponent> isn't the right return type, since the wrapped component should accept OwnProps, not the child's original props. Here's a polished version with better type handling, using a generic to support any OwnProps passed to the HOC:
import React, { ReactElement } from 'react' import { StoreState } from '../reducers' import { connect, MapStateToProps } from 'react-redux' // Props injected by Redux interface InjectedProps { auth: boolean } // Base props users can pass to the wrapped component interface BaseOwnProps {} export default function withAuth<OwnProps extends BaseOwnProps>( ChildComponent: React.ComponentType<OwnProps & InjectedProps> ): React.ComponentType<OwnProps> { class ComposedComponent extends React.Component<OwnProps & InjectedProps> { componentDidMount(): void { this.shouldNavigateAway() } componentDidUpdate(): void { this.shouldNavigateAway() } shouldNavigateAway = (): void => { if (!this.props.auth) { // Your navigation logic here } } render(): ReactElement { return <ChildComponent {...this.props} /> } } const mapStateToProps: MapStateToProps<InjectedProps, OwnProps, StoreState> = ({ auth }) => ({ auth }) // With global state config, you can omit the fourth generic here return connect<InjectedProps, {}, OwnProps>(mapStateToProps)(ComposedComponent) }
This version:
- Clearly separates injected Redux props from user-provided props
- Uses a generic to make the HOC reusable with any
OwnProps - Adds explicit typing for
mapStateToPropsfor extra safety
Final Notes
Either of the first two solutions will fix your initial error. The global config is ideal for larger projects to avoid repetition, while explicit generics work well for one-off cases. The refined HOC code will make your component more robust and easier to use correctly.
内容的提问来源于stack exchange,提问作者Florian Kuc

