TypeScript:如何正确收窄RouteLocationRaw联合类型以访问name属性
解决Vue Router RouteLocationRaw类型收窄问题
在开发带嵌套路由视图的步骤条组件时,使用RouteLocationRaw类型作为路由参数,对比路由name会触发TypeScript类型报错——原因是RouteLocationRaw是包含字符串、带path的路由对象、带name/params的路由对象的联合类型,其中前两者没有name属性。以下是具体解决方法:
方法一:直接通过类型判断收窄
在find回调中依次排除字符串类型,并判断对象是否包含name属性,让TypeScript自动收窄到带name的路由类型:
const activeRoute = computed(() => props.routes.find((propRoute) => { // 排除字符串格式的路由 if (typeof propRoute === 'string') return false; // 仅保留包含name属性的路由对象,TS会自动识别为对应类型 return 'name' in propRoute && propRoute.name === route.name; }))
方法二:自定义类型守卫(复用性更强)
如果需要在多个场景做相同的类型判断,可以定义类型守卫函数,明确告诉TypeScript如何识别带name的路由类型:
import type { RouteLocationRaw, RouteQueryAndHash, LocationAsRelativeRaw, RouteLocationOptions } from 'vue-router'; // 类型守卫:判断是否为带name的路由对象 function isNamedRoute(route: RouteLocationRaw): route is RouteQueryAndHash & LocationAsRelativeRaw & RouteLocationOptions { return typeof route !== 'string' && 'name' in route; } // 使用类型守卫收窄类型 const activeRoute = computed(() => props.routes.find((propRoute) => { return isNamedRoute(propRoute) && propRoute.name === route.name; }))
方法三:给props定义更精确的类型
如果组件仅接收带name的路由配置,可以直接给props.routes定义专属类型,从根源上避免联合类型问题:
import type { RouteRecordName, LocationQueryRaw, RouteParamsRaw, HistoryState } from 'vue-router'; // 定义仅包含name的路由类型 interface NamedStepRoute { name: RouteRecordName; query?: LocationQueryRaw; hash?: string; params?: RouteParamsRaw; replace?: boolean; force?: boolean; state?: HistoryState; } // 组件props定义 const props = defineProps<{ routes: NamedStepRoute[]; }>(); // 此时直接对比name不会触发类型报错 const activeRoute = computed(() => props.routes.find((propRoute) => propRoute.name === route.name))
内容的提问来源于stack exchange,提问作者Christopher Fimbel
相关产品推荐
相关产品推荐

