背景
在前端开发中,每次执行路由跳转,都需要小心翼翼的写 path
如果稍微写错一点点,那么将无法跳转页面
以 React 为例
而且 path 是纯字符串,没有 Typescript 类型提示
你写错了他也不会告诉你
如果你想有提示,只能自己手动挨个写类型,这很麻烦
那有没有一种办法,让 Typescript 自动推断我的 path 呢
当然有!!
解决方案一
as const
添加这个后就变成常量了,然后获取他的类型即可
在 Typescript 里,typeof 是获取他的类型
然后用中括号([]
),获取某个成员,可以是 字符串 、number
这里写 number 就是获取每个数组的成员
最后再取 path 字段,即可推导出路径类型
但是,好用吗?
还行吧,至少能用
麻烦吗?
有点麻烦,要挨个添加上 as const
如果对大型项目修改,还是有一定的工作量的
有更好地解决方案吗?
当然有,现在就来告诉你
解决方案二
先写个路由类型吧
ts
import type { RouteObject } from 'react-router-dom'
export type RouteItem<T extends string> =
Omit<RouteObject, 'path'>
& {
path: T
}
应该有些小伙伴会困惑,我是怎么知道 RouteObject 是 React 的路由类型呢?
我是怎么知道从哪导入的呢?
其实用 VSCode 就能知道
然后写上类型名字,按下 Ctrl + .
开启智能导入即可,详见我的文章教学
回到类型上来,我这个类型把原本的 path 排除掉,然后拼接上一个泛型
因为 React 定义的 path 类型是纯字符串 string
这种无法开启任何类型推断,必须用泛型才行
ts
import type { RouteObject } from 'react-router-dom'
export type RouteItem<T extends string> =
Omit<RouteObject, 'path'>
& {
path: T
}
const 泛型
ts
function genRoutes<const T extends string>(routes: RouteItem<T>[]) {
return routes
}
注意到了吗,我给函数的泛型加了 const
大多数人应该没用过吧?
那么他有什么效果呢?
接着往下看吧
利用这个函数,即可推断出类型,只需要把数组给他即可
看到了吗?我的 path 并没有标注 as const
但是返回的数组给我自动推断了
这样对于大型项目的改动侵入性,可以说为零
仅仅是添加一个函数即可实现
接下来取出路径类型即可,再重写一下路由方法即可
或者重写路由类型也行
ts
export type routePath = typeof myRoutes[number]['path']
重写路由方法
在 React 中,导出的路由对象上,有个 navigate 方法
如果不使用 Hook useNavigate 的话,用它也能实现路由导航
ts
export const router = createBrowserRouter(...)
接下来重新标注一下类型即可
Parameters 是拿到函数的参数,是个元组,取索引 [1],拿到配置类型
ts
/**
* 带有类型推断的路由跳转
*/
export const routerTo = (
path: routePath,
opts?: Parameters<typeof router['navigate']>[1]
) => {
router.navigate(path, opts)
}
更为彻底的,重写路由接口类型
写法就是排除掉原本的 navigate 函数类型
自己再重写一遍,可惜的是,React 没有导出 createBrowserRouter 的返回类型
所以无法实现了
ts
type NavigateParameters = Parameters<Router['navigate']>
type NavigateReturn = ReturnType<Router['navigate']>
type MyRouter = Omit<Router, 'navigate'> & {
navigate: (path: routePath, opts?: NavigateParameters[1]) => NavigateReturn
}
如果用 typeof 获取类型,又会循环引用自身
所以到此为止吧,功能已经实现了