I am using Typescript in a React project, and I have this code that I got with the help of Chatgpt:
import React from "react";
import { Route, Navigate, RouteProps } from "react-router-dom";
import { useAuth } from "./AuthContext";
interface PrivateRouteProps extends RouteProps {
children?: React.ReactNode;
}
const PrivateRoute: React.FC<PrivateRouteProps> = ({ children, ...rest }) => {
const { token } = useAuth();
return (
<Route
{...rest}
element={token ? children : <Navigate to="/login" replace />}
/>
);
};
export default PrivateRoute;
It is showing this error:
An interface can only extend an object type or intersection of object
types with statically known members.
The error is coming from "extends RouteProps" in this line:
interface PrivateRouteProps extends RouteProps {
children?: React.ReactNode;
}
2
Answers
This is happening because RouteProps isn’t an interface, it’s a union of multiple interfaces. From the react-router-dom 6.3.0 type definitions:
You can’t extend an interface from a union, but you can do essentially the same thing with a type intersection:
There are some very slight differences between extending an interface and doing an intersection, but they rarely matter. If you’d like to know more see: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces
The basic issue is that you can’t extend a type declaration, you can only extend interfaces. Nicholas’s answer addresses this sufficiently and there is not more I could add.
Source
You can "extend" the union. Something along the following:
But
But after you fix the Typescript issue you are going to run into React-Router-DOM issues trying to use this
PrivateRoute
component.Route
componentchildren
can only be anotherRoute
component.Route
component can’t be rendered directly, it can only be rendered as a child of theRoutes
component, or theRoute
component in the case of nested routes.Instead of rendering a
children
prop, anOutlet
component should be rendered for the nested routes to render out their content. This also really simplifies the implementation.Example:
Usage: