Search code examples
reactjstypescriptreact-router-v4

React TypeScript: Correct types for Route location and children properties


I have a router that passes props of location and children, but I don't know what the correct types are for these props.

This is the router using react-router-dom...

import React, { useReducer } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { globalContext, setGlobalContext } from './components/context';
import { Layout } from './components/layout';
import { defaultState, globalReducer } from './components/reducer';
import { Home } from './routes/home';
import { NotFound } from './routes/notFound';

const Router: React.FC = () => {
  const [global, setGlobal] = useReducer(globalReducer, defaultState);
  return (
    <setGlobalContext.Provider value={{ setGlobal }}>
      <globalContext.Provider value={{ global }}>
        <BrowserRouter>
          <Route
            render={({ location }) => (
              <Layout location={location}>
                <Switch location={location}>
                  <Route exact path='/' component={Home} />
                  <Route component={NotFound} />
                </Switch>
              </Layout>
            )}
          />
        </BrowserRouter>
      </globalContext.Provider>
    </setGlobalContext.Provider>
  );
};

export { Router };

and inside layout component, I have an interface for the location and children, but because I don't know the correct type for these I end up using any, my linter then throws a fit.

import React from 'react';

interface PropsInterface {
  children: any;
  location: any;
}

const Layout: React.FC<PropsInterface> = (props: PropsInterface) => {
  return (
    <div>
      <p>{props.location}</p>
      <p>{props.children}</p>
    </div>
  );
};

export { Layout };

The error I get is Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type. (no-any)tslint(1)

Could I get location from import import { useLocation } from 'react-router-dom';


Solution

  • The interface for Route that you're looking for can be found in the @types/react-router definition.

    After installing that in your project, you should be able to silence that TS error with an interface like this:

    // Layout.tsx
    
    import { RouteProps } from "react-router";
    
    interface ILayoutProps {
      location: RouteProps["location"];
      children: RouteProps["children"];
    }
    
    const Layout: React.FC<ILayoutProps> = (props: ILayoutProps) => {
      return <div>{props.children}</div>;
    };
    

    Keep in mind, location is an object, so React isn't going to let you render that as you were previously.

    Here's a link to a working sample: https://codesandbox.io/s/zealous-snyder-yw9dg


    Another option is to use a Partial interface, but that will make all the ILayoutProps optional:

    interface ILayoutProps extends Partial<RouteProps> {}