考虑以下代码:
const router = useRouter()
await router.push({
name: 'NonExistingRoute', // no typescript error ):
})
给出了一个不存在的路由名称,但没有发生 TypeScript 错误。相反,该问题只会在运行时被注意到。有什么方法可以得到编译时错误吗?
也许你可以把它包装在一个只接受类型路由字符串的实用函数中
const router = useRouter()
export type NamedRoute = "login" | "logout" | "user-profile";
export async function goToNamedRoute(name: NamedRoute): Promise<void> {
return router.push({name});
}
简而言之
对于存在的编译错误,代码需要有明显的错误,引用不存在的文件,语法错误等
听起来您确实想在这里解决其他一些问题……即为什么你的应用程序中有不存在的路线名称?
无论如何,也许您可以通过编程方式避免错误,例如
let r = router.resolve({name: 'NonExistingRoute'});
if (r.resolved.matched.length > 0){
// exists
} else {
// doesn't exist
}
如果你想依赖 Typescript 来检测错误的路由,你可能只使用枚举或封闭类型?,尽管这肯定需要一些组合。可能的一种方法是:
enum Cities {
NY,
London
}
function routeCreator(city: Cities, restOfPath?: string){
//combine paths somehow, e.g.
if(!restOfPath) return `/${Cities[city]}/`;
return `/${Cities[city]}/${restOfPath}`
}
我对这个困境的解决方案
在 routes.ts 中定义你的路线
import { RouteLocationRaw } from 'vue-router'
type RouteFunction = (...args: any[]) => RouteLocationRaw
export const routes = {
login: () => ({ name: 'Login' }) as const,
viewProfile: (userId: string) => ({ name: 'ViewProfile', params: { userId } }) as const,
...
} satisfies Readonly<Record<string, RouteFunction>>
export type Routes = typeof routes
export type NamedRoute = ReturnType<Routes[keyof Routes]>['name']
请注意,每条路线都需要是
as const
,否则打字稿会将['name']属性扩大到任何string
.
然后实际的路由器被定义为
import { RouteRecordRaw, createRouter, createWebHistory } from 'vue-router'
import { NamedRoute } from '@/router/routes'
type NamedRouteRecordParent = { name?: NamedRoute, children: NamedRouteRecord[] }
type NamedRouteRecordChild = { name: NamedRoute }
type NamedRouteRecord = Omit<RouteRecordRaw, 'name' | 'children'> & NamedRouteRecordParent | NamedRouteRecordChild
const routes: NamedRouteRecord[] = [
{ name: 'Login', path: '/login' },
{ name: 'ViewProfile', path: '/view-profile/:userId' },
]
export const router = createRouter({
history: createWebHistory(),
routes: routes as RouteRecordRaw[],
})
强制开发人员仅命名与
routes.ts
中找到的记录相匹配的路由。如所写,“父”记录不必命名。