3
votes

I have a component that wraps Router and takes an additional props. I tried using PropsWithoutRef in a way that's analogous to the use in this cheatsheet:

import React, { ComponentType, PropsWithoutRef } from 'react'
import { Route } from 'react-router'

type LayoutRouteProps = PropsWithoutRef<Route> & {
    component: ComponentType,
};


const DashboardLayoutRoute = ({
    component: Component,
    ...rest
}: LayoutRouteProps) => {
    const render = (props: any)=> <Component {...props} />

    return <Route {...rest} render={render} />
};

But it did no good. When I try to use DashboardLayoutRoute and pass props relevant to Route:

<DashboardLayoutRoute exact path='/' component={Home} />

I get

Error:(63, 39) TS2322: Type '{ exact: true; path: string; component: any; }' is not assignable to type 'IntrinsicAttributes & Route & { component: ComponentType<{}>; }'.

Property 'exact' does not exist on type 'IntrinsicAttributes & Route & { component: ComponentType<{}>; }'.

Error:(66, 39) TS2322: Type '{ path: string; component: any; }' is not assignable to type 'IntrinsicAttributes & Route & { component: ComponentType<{}>; }'.

Property 'path' does not exist on type 'IntrinsicAttributes & Route & { component: ComponentType<{}>; }'.

What's wrong with my code?

2

2 Answers

5
votes

Found the solution further in the same cheatsheet!

The correct way to extract props from a component is not via PropsWithoutRef but via React.ComponentProps (or React.ComponentPropsWithoutRef) in combination with typeof:

import React, { ComponentType, ComponentProps } from 'react'
import { Route } from 'react-router'

type LayoutRouteProps = ComponentProps<typeof Route> & {
    component: ComponentType,
};

But as Mor Shemesh pointed out in his answer, it's probably better to import the type instead when you can:

import React, { ComponentType } from 'react'
import { Route, RouteProps } from 'react-router'


type LayoutRouteProps = RouterProps & {
    component: ComponentType,
};
2
votes

I can recommend using the

import * as React from "react";
import { render } from "react-dom";
import { Route, RouteProps } from "react-router";

class Home extends React.Component {
    render() {
        return <div>Home</div>;
    }
}

type LayoutRouteProps = RouteProps & {
    component: React.ComponentType;
}

const DashboardLayoutRoute = ({
    component, 
    ...rest
    }: LayoutRouteProps) => {
        const ComponentClass = component;
        const render = (props: any) => <ComponentClass {...props} />;

        return <Route {...rest} render={render} />;
}

const renderRoot = () => (
    <DashboardLayoutRoute exact path="/" component={Home} />
);