React-router + typescript type error
While building my application to interact with typescript, I ran into a small problem that I haven't been able to solve yet.
My code:
App.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import * as promise from 'redux-promise';
import reducers from './reducers';
import TemplateNavTop from './components/layout/template-nav-top';
const TestComponent2 = () => {
return <h1>TestComponent</h1>;
}
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<Switch>
<Route path="/" exact component={TestComponent} />
<Route path="/checkout">
<TemplateNavTop>
<TestComponent2 />
</TemplateNavTop>
</Route>
</Switch>
</BrowserRouter>
</Provider>
, document.getElementById('root')
pattern-nav-top
import * as React from 'react';
import NavTop from './nav-top/nav-top';
export default class TemplateNavTop extends React.Component<any, {}> {
render() {
return (
<div>
asd
{this.props.children}
Footer
</div>
);
}
}
The problem appears in the / checkout route where it complains about the following:
Type '{ path: "/checkout"; children: Element; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Route> & Readonly<{ children?: ReactNode; }> & Rea...'.
Type '{ path: "/checkout"; children: Element; }' is not assignable to type 'Readonly<RouteProps>'.
Types of property 'children' are incompatible.
Type 'Element' is not assignable to type '(props: RouteComponentProps<any>) => ReactNode'.
I found out that the workaround works:
<Route path="/checkout" component={() => TemplateWithNavBar(<TestComponent2 />)} />
But I would rather do it right, could anyone here help me?
Edit: I have @types installed
source to share
Edit and TL; DR: Just update the type declarations with
npm install --save-dev @types/react-router
Description
This is an error in the declaration files. The problem is that it was originally intended that the type of children would be
((props: RouteComponentProps<any>) => React.ReactNode | React.ReactNode)
which is indeed a function that returns a union React.ReactNode | React.ReactNode
that collapses to a simple one React.ReactNode
.
In fact it should have been
((props: RouteComponentProps<any>) => React.ReactNode) | React.ReactNode
I've opened a pull request for you here .
I must mention that you cannot depend on this behavior. Almost all examples I can find on the internet use an explicit for attribute children
when passed to a function with a react router. Even the documentation itself says that it only accepts a function (not an element or whatever).
source to share