如何将组件定义的类型继承到react-router-dom的路由跳转方法中?
最优解决方案
核心思路是统一维护路由与传参类型的映射关系,扩展 React Router 内置类型实现跳转时的自动类型校验,避免两端类型声明不一致的问题。
步骤1:抽离公共路由类型定义
新建单独的路由类型文件(比如 src/types/routes.ts),统一管理所有路由的路径与对应接收的 state 类型:
// src/types/routes.ts // 目标页接收的state类型,统一在这里定义避免重复声明 export interface SomeStuffProps { stuff: string; moreStuff: string; } // 全局路由映射:key为路由路径,value为该路由接收的state类型 export interface RouteStateMap { "/display": SomeStuffProps; // 其余有传参需求的路由可以在此追加 // "/detail": { id: number; name: string } [key: string]: unknown; }
步骤2:扩展React Router内置类型
针对使用 v5 版本 useHistory 的场景
新增类型声明文件扩展 history 包的 History 类型,让 push/replace 方法自动匹配传入路径对应的 state 类型:
// src/types/react-router.d.ts import { RouteStateMap } from "./routes"; import { History } from "history"; declare module "history" { export interface History<S = unknown> { push<P extends keyof RouteStateMap>( path: P, state?: RouteStateMap[P] ): void; replace<P extends keyof RouteStateMap>( path: P, state?: RouteStateMap[P] ): void; } }
针对使用 v6 版本 useNavigate 的场景
扩展 react-router 包的 NavigateFunction 类型即可,逻辑与v5一致:
// src/types/react-router.d.ts import { RouteStateMap } from "./routes"; import { NavigateFunction } from "react-router"; declare module "react-router" { export interface NavigateFunction { <P extends keyof RouteStateMap>( to: P, options?: { state?: RouteStateMap[P]; replace?: boolean } ): void; } }
步骤3:业务侧使用
跳转页调用逻辑
不需要手动声明state类型,TS会自动根据传入的路径校验state格式:
// /new-post 页面代码 import { useHistory } from "react-router-dom"; // v5版本 // v6版本导入 import { useNavigate } from "react-router-dom" const history = useHistory(); // 传入"/display"时自动校验state是否符合SomeStuffProps要求 history.push("/display", { stuff: "内容1", moreStuff: "内容2" }); // 类型错误时会直接触发编译报错,提前发现问题 // history.push("/display", { stuff: 123 }) // 会提示stuff类型不匹配
目标页取值逻辑
直接从全局路由映射中取对应路径的state类型,不需要重复导入单独的Props类型:
// /display 页面代码 import { useLocation } from "react-router-dom"; import { RouteStateMap } from "@/types/routes"; // state自动获得SomeStuffProps类型 const location = useLocation<RouteStateMap["/display"]>(); const { stuff, moreStuff } = location.state;
方案优势
- 所有路由传参类型统一维护,修改时只需调整一处,两端自动同步
- 跳转时自动校验类型,避免手动声明类型的人为错误
- 不需要在跳转页重复引入目标组件的Props类型,耦合度更低
如果项目规模很小不想做全局类型扩展,也可以选择把state类型抽离为公共类型,两端直接引用同一个类型定义,虽然没有路径与类型的自动绑定校验,也能避免两端类型定义不一致的问题。
内容的提问来源于stack exchange,提问作者user13121182
相关产品推荐
相关产品推荐

