879 words
4 minutes
使用 TypeScript 和 React Router 进行安全导航
2025-08-11 21:03:39
2025-08-14 22:24:34

为什么基于字符串的路由会失败#

const navigate = useNavigate(); // 应用中的某处 navigate('/dashboard/items/42/edit'); // 应用中的其他地方 navigate('/dashboard/items/' + itemId + '/edit'); // 糟糕,拼写错误 navigate('/dasboard/items/42/edit'); // 404

在基于字符串的路由中,路径只是字符串。TypeScript 无法验证它们,提供自动完成功能,或警告你有拼写错误。如果你重命名路由或重构 URL 结构,应用可能会悄无声息地崩溃 — 在拥有数百个路由的大型应用中尤其痛苦。

什么是类型安全路由?#

类型安全路由用类型化的路由构建器和经过验证的参数替代脆弱的字符串。不再是这样写:

navigate('/dashboard/items/42/edit');

而是这样写:

navigate(routes.dashboard.items.edit({ id: '42' }));

现在,TypeScript 会验证:

  • /dashboard/items/edit 是一个有效的路径
  • id 参数是必需的且类型正确
  • 路由结构的任何更改都会反映在整个应用中

好处包括:

  • IDE 自动完成
  • 编译时验证
  • 更简单、更安全的重构

使用 React Router v6 和 TypeScript 的基本设置#

首先定义所有可能的路由及其参数类型:

interface AppRoutes { '/': {}; '/dashboard': {}; '/dashboard/items': {}; '/dashboard/items/:id': { id: string }; '/dashboard/items/:id/edit': { id: string }; }

现在创建一个类型安全的导航钩子:

import { useNavigate } from 'react-router-dom'; function useTypedNavigate<T extends keyof AppRoutes>() { const navigate = useNavigate(); return (path: T, params?: AppRoutes[T]) => { let url = path as string; if (params) { for (const [key, value] of Object.entries(params)) { url = url.replace(`:${key}`, value); } } navigate(url); }; }

你还可以为路由参数安全性类型化 useParams

import { useParams } from 'react-router-dom'; function useTypedParams<T extends keyof AppRoutes>() { return useParams() as AppRoutes[T]; } // 使用方法 const { id } = useTypedParams<'/dashboard/items/:id/edit'>();

集中管理路由#

export const routeConfig = { home: '/', dashboard: { root: '/dashboard', items: { list: '/dashboard/items', edit: '/dashboard/items/:id/edit', create: '/dashboard/items/new', }, }, } as const;

使用 TypeScript 的推断功能自动派生路径类型,减少重复并确保一致性。

使用现代库#

如果你正在构建大型应用,考虑使用那些开箱即支持类型化路由的库:

示例:TanStack Router#

const itemEditRoute = new Route({ getParentRoute: () => dashboardRoute, path: '/items/$itemId/edit', component: ItemEdit, }); function ItemEdit() { const { itemId } = itemEditRoute.useParams(); // itemId 的类型为 string }

渐进式采用策略#

你不需要一次性重写整个应用。相反:

  1. 为新功能引入 useTypedNavigate 和 useTypedParams
  2. 逐步重构旧组件
  3. 使用 lint 规则强制保持一致性

ESLint 示例:#

"rules": { "no-hardcoded-routes": "error" }

这条规则防止在导航中使用原始字符串,强制执行你的类型化路由系统。

类型化路由的亮点#

类型安全路由在以下场景特别有用:

  • 管理仪表板:数十个视图和深度链接
  • 电子商务应用:动态过滤器和嵌套路由
  • 带有状态 URL 的单页应用:与 Redux、Zustand 或基于 URL 的状态集成

示例:

interface ECommerceRoutes { '/shop': {}; '/shop/:category': { category: string }; '/shop/:category/:itemId': { category: string; itemId: string }; '/checkout': {}; }

与状态管理器集成,如 Zustand

const useStore = create((set) => ({ currentRoute: '/', navigateTo: (route: keyof AppRoutes) => set({ currentRoute: route }), }));

最终思考#

类型安全导航正在成为现代 React 开发的标准。它提高了信心,防止运行时故障,并使重构变得无痛 — 尤其是在大型应用中。

如果你的应用仍然依赖基于字符串的路径,你可能在浪费时间调试可预防的问题。采用类型化路由意味着减少因单个拼写错误的 URL 而导致的周五晚上部署灾难。

banner

加入我们,共译前端好文

我们不靠算法推荐,而是靠前端开发者对技术趋势的敏锐、对知识分享的热爱,手动为你筛选每周全球社区中最新、最热、最值得关注的前端文章。@海外前端动态情报源清单(持续更新)

qrcode
使用 TypeScript 和 React Router 进行安全导航
https://0bipinnata0.my/posts/weekly-translate/navigate-safely-with-typescript-and-react-router/
Author
0bipinnata0
Published at
2025-08-11 21:03:39