typescriptvue.jsvuejs3vue-composition-apiunplugin-vue-router

Route parameter typing error with TypeScript and unplugin-vue-router


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; }'."

TypeScript error with unplugin-vue-router

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?


Solution

  • 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.