SolvedDefinitelyTyped [@types/react-router] Type restriction for RouteProps.component creates error

I'm using react-dom-router (which internally uses react-router) to define some routes, but as soon as I include the d.ts file and run tsc I get the following error:

ClientApp/routes.tsx(9,12): error TS2322: Type '{ exact: true; path: "/"; component: typeof Home; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Route> & Readonly<{ children?: ReactNode; }> & Rea...'.
  Type '{ exact: true; path: "/"; component: typeof Home; }' is not assignable to type 'Readonly<RouteProps>'.
    Types of property 'component' are incompatible.
      Type 'typeof Home' is not assignable to type 'StatelessComponent<RouteComponentProps<any>> | ComponentClass<RouteComponentProps<any>>'.
        Type 'typeof Home' is not assignable to type 'ComponentClass<RouteComponentProps<any>>'.
          Type 'Home' is not assignable to type 'Component<RouteComponentProps<any>, ComponentState>'.
            Types of property 'props' are incompatible.
              Type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>' is not assignable to type 'Readonly<{ children?: ReactNode; }> & Readonly<RouteComponentProps<any>>'.
                Type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>' is not assignable to type 'Readonly<RouteComponentProps<any>>'.
                  Property 'match' is missing in type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'.

I've narrowed it down to the following line in v3/index.d.ts:67

component?: React.SFC<RouteComponentProps<any> | undefined> | React.ComponentClass<RouteComponentProps<any> | undefined>;

EDIT: At first I thought the order was the problem but turns out I put in a typo in my fix.

component?: React.ComponentClass<RouteComponentProps<any> | undefined | React.SFC<RouteComponentProps<any> | undefined>>;

Notice that React.SFC is inside the brackets of React.ComponentClass. I don't know why this fixes my problem, but I'm pretty sure that this is not a valid solution.
EDIT END

When you change the order of React.SFC and React.ComponentClass everything works fine for me. But since I'm pretty new to TypeScript and React I don't know if there are any possible side effects in doing so. I really hope someone of the authers can give me some insight. If there are no problems with changing this line I would be happy to create a PR.

My Code:
route.tsx

import * as React from 'react';
import { Route } from 'react-router-dom';
import { Layout } from './components/Layout';
import { Home } from './components/Home';

export const routes = <Layout>
    <Route exact path='/' component={ Home } />
</Layout>;

app.tsx

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import * as RoutesModule from './routes';
let routes = RoutesModule.routes;

function renderApp() {
    ReactDOM.render(
        <AppContainer>
            <BrowserRouter children={ routes } />
        </AppContainer>,
        document.getElementById('react-app')
    );
}

renderApp();

Home.tsx

import * as React from 'react';

export class Home extends React.Component<{}, {}> {
    public render() {
        return <div>
        </div>;
    }
}
31 Answers

✔️Accepted Answer

The component is required to be able to receive RouteComponentProps. Change your extends React.Component<{}, {}> clause to extends React.Component<{} & RouteComponentProps<{}>, null>

Since the left side of & is an empty {} you can just omit that and only put RouteComponentProps there, but that is how you would combine multiple props coming from other higher order components (e.g. react-redux's compose).

Other Answers:

I got it working by doing this:

import { withRouter, RouteProps } from 'react-router';
...
class Layout extends React.Component<Props & RouteProps, State> 
...

I have managed to solve this by casting as any when I am doing the withRouter export. I know this isn't ideal but it has got me out of a hole.

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

...

export class ExampleContainer extends React.Component<ExampleComponentProps & RouteProps, undefined> {

...

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ExampleContainer) as React.ComponentType<any>);

Above didn't work for me, if anyone is interested this does, gives you all types for history, location, match

class SignInPage extends React.Component<RouteComponentProps<any>>

This should work:

import { RouteComponentProps } from 'react-router-dom';

type MyProps = RouteComponentProps<{ id?: string }>

const CoolThing: React.FC<MyProps> = ({ match }) => {
  const id = match.params.id;

  return (
    <div>Hopefully that helps!</div>
  );
}

export default CoolThing;

More Issues: