You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:配置存组件引用,渲染时实例化(最常用)

这种写法适合需要根据运行时上下文给路由组件动态传参的场景,灵活性更高。

  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 },
];
  1. 修改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要求:

  1. 修改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 /> },
];
  1. 渲染时直接传入配置里的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:45:06