React Router v6如何正确定义路由配置的TypeScript类型
React Router v6 TypeScript 路由类型报错修复方案
核心报错原因
Type 'ComponentType<{}>' is not assignable to type 'ReactNode'
这个报错的本质是类型不匹配:
- 你自定义的
IRoute接口中element字段类型为React.ComponentType,这个类型指代组件本身的引用(比如直接写Login、Event这种导入的组件函数/类) - 但React Router v6的
<Route />组件要求element属性传入实例化后的React节点,也就是JSX写法的<Login />,对应类型为ReactNode
直接把组件引用传给需要ReactNode的属性,就会触发TS类型校验错误。
另外你的代码里还有两个小问题:
RouteNames.LOGIN的路径写为./login属于笔误,前端路由路径需以/开头- 遍历生成Route时没有加
key属性,会触发React遍历渲染警告
修复方案
你可以根据自己的编码习惯选以下任意一种方案,都可以完全消除类型报错。
方案1:配置存组件引用,渲染时实例化(最常用)
这种写法适合需要根据运行时上下文给路由组件动态传参的场景,灵活性更高。
- 保留原有
IRoute接口定义,顺手修复路径笔误:
import Event from "../pages/Event"; import Login from "../pages/Login"; export enum RouteNames { LOGIN = "/login", // 修复路径笔误 EVENT = "/", } export interface IRoute { path: string; element: React.ComponentType; } export const publicRoutes: IRoute[] = [ { path: RouteNames.LOGIN, element: Login }, ]; export const privateRoutes: IRoute[] = [ { path: RouteNames.EVENT, element: Event }, ];
- 修改AppRouter的渲染逻辑,遍历渲染时将组件转为JSX实例,同时补上遍历需要的
key属性:
import { Routes, Route, Navigate } from "react-router-dom"; import type { FC } from "react"; const AppRouter: FC = () => { const isAuth = true; // 合并路由配置减少重复JSX const routes = isAuth ? privateRoutes : publicRoutes; return ( <div> <Routes> {routes.map((route) => ( {/* 核心改动:将组件引用转为JSX实例,同时补key */} <Route key={route.path} path={route.path} element={<route.element />} /> ))} {/* 可选:添加兜底路由 */} <Route path="*" element={<Navigate to={isAuth ? RouteNames.EVENT : RouteNames.LOGIN} replace />} /> </Routes> </div> ); };
方案2:配置直接存储JSX节点
如果你的路由组件不需要动态传参,可以直接在配置里写好JSX节点,让element字段类型直接匹配ReactNode要求:
- 修改
IRoute接口和路由配置:
import type { ReactNode } from "react"; import Event from "../pages/Event"; import Login from "../pages/Login"; export enum RouteNames { LOGIN = "/login", EVENT = "/", } export interface IRoute { path: string; element: ReactNode; // 类型改为ReactNode } export const publicRoutes: IRoute[] = [ { path: RouteNames.LOGIN, element: <Login /> }, // 直接写JSX ]; export const privateRoutes: IRoute[] = [ { path: RouteNames.EVENT, element: <Event /> }, ];
- 渲染时直接传入配置里的element即可:
{routes.map((route) => ( <Route key={route.path} path={route.path} element={route.element} /> ))}
方案3:直接复用React Router官方内置类型(推荐)
React Router v6本身已经提供了完整的路由配置类型RouteObject,完全不需要自己写IRoute接口,类型和官方实现100%对齐,后续如果要加嵌套路由、loader、action、errorElement等配置属性,也会有完整的类型提示:
import type { RouteObject } from "react-router-dom"; import Event from "../pages/Event"; import Login from "../pages/Login"; export enum RouteNames { LOGIN = "/login", EVENT = "/", } // 直接用官方RouteObject作为路由数组类型 export const publicRoutes: RouteObject[] = [ { path: RouteNames.LOGIN, element: <Login /> }, ]; export const privateRoutes: RouteObject[] = [ { path: RouteNames.EVENT, element: <Event /> }, ];
后续渲染逻辑和方案2完全一致,不需要额外处理类型。
内容的提问来源于stack exchange,提问作者egatsak
相关产品推荐
相关产品推荐

