theycallmemorty
theycallmemorty

Reputation: 12962

Using react-router with typescript

I'm attempting to port a small react app over to typescript.

I'm encountering issues with react-router. I have the latest definitions from definitely type but the following code gives me errors:

var routes:Router.Route = (
<Route name="root" path="/" handler={MyApp}>
  <Route path="dashboard" handler={MyDash} />
  <DefaultRoute handler={SomeSection} />
  <NotFoundRoute handler={NotFoundPage} />
</Route>
);

Router.run(routes, function (Handler:React.Component<any, any>) {
  React.render(<Handler/>, document.body);
});

These are the compilation errors I get:

js/app.tsx(31,3): error TS2605: JSX element type 'Component<RouteProp, any>' is not a constructor function for JSX elements.
  Property 'render' is missing in type 'Component<RouteProp, any>'.
js/app.tsx(32,5): error TS2605: JSX element type 'Component<RouteProp, any>' is not a constructor function for JSX elements.
js/app.tsx(47,5): error TS2605: JSX element type 'Component<DefaultRouteProp, any>' is not a constructor function for JSX elements.
  Property 'render' is missing in type 'Component<DefaultRouteProp, any>'.
js/app.tsx(49,5): error TS2605: JSX element type 'Component<NotFoundRouteProp, any>' is not a constructor function for JSX elements.
  Property 'render' is missing in type 'Component<NotFoundRouteProp, any>'.
js/app.tsx(53,20): error TS2345: Argument of type '(Handler: Component<any, any>) => void' is not assignable to parameter of type '(Handler: RouteClass, state: RouterState) => void'.
  Types of parameters 'Handler' and 'Handler' are incompatible.
    Type 'Component<any, any>' is not assignable to type 'RouteClass'.
js/app.tsx(54,17): error TS2604: JSX element type 'Handler' does not have any construct or call signatures.

What is the correct way to initialize a set of react-router routes using typescript?

(I should clarify that I'm using a nightly typescript build which has support for JSX via the --jsx react flag

Upvotes: 11

Views: 12793

Answers (3)

Xavier M&#233;haut
Xavier M&#233;haut

Reputation: 123

For making it running under typescript 1.6 with react-router, I've added the following code in the react-router.d.ts file :

interface RouterClass extends React.ComponentClass<any> {}

var Router: RouterClass;

//For Router

function createElement(

type: ReactRouter.RouterClass,

props: any,

...children: __React.ReactNode[]): ReactRouter.Router;

}

interface RouteProp {
    name?: string;
    path?: string;
    handler?: React.ComponentClass<any>;
    ignoreScrollBehavior?: boolean;
    component?: React.ComponentClass<any>;
}

Upvotes: -1

Ryan Cavanaugh
Ryan Cavanaugh

Reputation: 220944

The root problem was some definitions in react-router not having an explicit render() method. This has been fixed (indirectly) by https://github.com/borisyankov/DefinitelyTyped/pull/5197

Note that this code is incorrect:

Router.run(routes, function (Handler:React.Component<any, any>) {
  React.render(<Handler/>, document.body);
});

It should be:

Router.run(routes, function (Handler: new() => React.Component<any, any>) {
  React.render(<Handler/>, document.body);
});

Because Handler is a constructor for a React component, not an instance of it.

Upvotes: 15

curpa
curpa

Reputation: 2400

Errors in the type definitions appears to be the cause. You can work around them by modifying the .d.ts files as follows:

In react.d.ts, remove render from the JSX.ElementClass interface

interface ElementClass extends React.Component<any, any> {
}

In react-router.d.ts, change run method's routes parameter's type to React.ReactElement<RouteProp>

function run(routes: React.ReactElement<RouteProp>, callback: RouterRunCallback): Router;
function run(routes: React.ReactElement<RouteProp>, location: LocationBase, callback: RouterRunCallback): Router;

Upvotes: 0

Related Questions