I'm learning Vue 3 with the Composition API using TypeScript. One of the tutorials I'm doing suggests using unplugin-vue-router to autogenerate routes based on file naming/path conventions. The plugin works correctly, but TypeScript is upset about route parameters. For example, I have this basic Vue page:
<script setup lang="ts">
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
<template>
<div>
<h1>Page slug: {{ route.params?.slug }}</h1>
</div>
</template>
TypeScript is highlighting slug
and warning that "Property 'slug' does not exist on type 'Record<never, never> | { catchAll: string; } | { slug: string; } | { id: string; }'."
Doing some Googling, I found this exact problem as an issue on the unplugin-vue-router Github site, but the suggestion to "use type narrowing" is vague and doesn't really work in this situation, as far as I can tell.
How can I get rid of this TypeScript error when using route parameters and unplugin-vue-router?
You can provide a type to useRoute like this:
const route = useRoute<'ProductDetails'>()
The type for 'ProductDetails' comes from the RouteNamedMap provided by unplugin-vue-router:
'ProductDetails': RouteRecordInfo<'ProductDetails', '/products/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
However, this approach may currently result in the following TypeScript error: Type '"ProductDetails"' does not satisfy the constraint 'keyof RouteNamedMap'.
Attending to the documentation you can find:
// these are all valid
let userWithId = useRoute() as RouteLocationNormalizedLoaded<'/users/[id]'>
userWithId = useRoute<'/users/[id]'>()
// 👇 this one is the easiest to write because it autocompletes
userWithId = useRoute('/users/[id]')
userWithId.params
So there might be one for you.