【奇淫技巧】让你的路由跳转拥有TS类型提示,告别人工记路由path

背景

在前端开发中,每次执行路由跳转,都需要小心翼翼的写 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 + .

开启智能导入即可,详见我的文章教学

# 【最高效编码指南】也许你不会用VSCode

# VSCode 工具技巧集合

回到类型上来,我这个类型把原本的 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 获取类型,又会循环引用自身

所以到此为止吧,功能已经实现了

相关推荐
还是大剑师兰特6 分钟前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
m0_7482361114 分钟前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo61727 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_7482489429 分钟前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_7482356140 分钟前
从零开始学前端之HTML(三)
前端·html
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink6 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者7 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-8 小时前
验证码机制
前端·后端
燃先生._.9 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js