8

While creating my react app with typescript I ran into a small issue that I have not been able to solve just 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')

template-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 the the following workaround does work:

<Route path="/checkout" component={() => TemplateWithNavBar(<TestComponent2 />)} />

But I'd rather do it the right way, anyone here able to help me out?

Edit: I Do have the @types installed

1
  • I have a feeling this is a slight bug with [the react-router.d.ts file](((props: RouteComponentProps<any>) => React.ReactNode | React.ReactNode)).children is defined as ((props: RouteComponentProps<any>) => React.ReactNode | React.ReactNode) which I heavily suspect should be ((props: RouteComponentProps<any>) => React.ReactNode) | React.ReactNode Commented May 30, 2017 at 7:19

1 Answer 1

13

Edit and TL;DR: Just upgrade your type declarations with

npm install --save-dev @types/react-router

Explanation

This is a bug in the declaration files. The problem is was that the type of children was originally expected to be

((props: RouteComponentProps<any>) => React.ReactNode | React.ReactNode)

which really is a function that returns a union of React.ReactNode | React.ReactNode which collapses down to a simple React.ReactNode.

What it really should have been was

((props: RouteComponentProps<any>) => React.ReactNode) | React.ReactNode

I've opened up a pull request for you here.

I should mention that you may not want to take a dependency on this behavior. Almost all examples I can find online use an explicit attribute for children while passing in a function with react-router. Even the documentation itself says that it only takes a function (rather than an element or anything else).

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for your help and the advice!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.