issue with types when using "withRouter" and Typescript

As of documentation, withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.

So MenuItem component should have props to receive them. For now, MenuItem component has props of type ISection which does not include router props.

The easiest way to add router props is to intersect ISection with RouteComponentProps.

import { withRouter, RouteComponentProps } from "react-router-dom";

// ...
class MenuItem extends React.Component<ISection & RouteComponentProps> {

Full code is

import * as React from 'react';
import { withRouter, RouteComponentProps } from "react-router-dom";

interface ISection {
    id: number;
    title: string;
    imageUrl: string;
    size: string;
}

class MenuItem extends React.Component<ISection & RouteComponentProps> {
    render() {
        return (
            <div className={`${this.props.size} menu-item`}>
                <div
                    className="background-image"
                    style={{ backgroundImage: `url(${this.props.imageUrl})` }}
                />
                <div className="content">
                    <h1 className="title">{this.props.title}</h1>
                    <span className="subtitle">some subtitle</span>
                </div>
            </div>
        );
    }
}

export default withRouter(MenuItem);

And answers to your questions

  1. Why does it say "type 'typeof MenuItem'"? Shouldn't it just say the type of 'MenuItem' instead of the function to obtain the type?

    Error arisen from types incompatibility. MenuItem is class, not type. To get type of MenuItem you should use typeof MenuItem. So typeof MenuItem is type. And compiler says correctly, "type typeof MenuItem".

  2. Is it necessary for withRouter to work with class components, or does it also work on functional components?

    It is allowed to work with class component and with functional component.

    This is how your component will look like if implemented as functional

    const Cmp1: React.FunctionComponent<ISection & RouteComponentProps> = (props) => {
        return (
            <div className={`${props.size} menu-item`}>
                <div
                    className="background-image"
                    style={{ backgroundImage: `url(${props.imageUrl})` }}
                />
                <div className="content">
                    <h1 className="title">{props.title}</h1>
                    <span className="subtitle">some subtitle</span>
                </div>
            </div>
        );
    }
    
    const WrappedCmp = withRouter(Cmp1);
    
  3. Do I need to connect() something, or map Props onto State? If so, why?

    No, this is not strict requirement. connect is part of Redux, so if you use Redux you may connect. Here is documentation of how to use withRouter with connect. But again, it is not required.

  4. And lastly, how can I fix this?

    Already answered. See above :-)


For anyone coming here for Next.js intersect your props interface alongside WithRouterProps like so..

import { WithRouterProps } from "next/dist/client/with-router";

class MenuItem extends React.Component<IProps & WithRouterProps>