Skip to content

TS errors in some page components when using auto-typed $route and useRoute (with unplugin-vue-router/volar/sfc-typed-router) #685

@Anoesj

Description

@Anoesj

Taken from this comment by @darkbasic (slightly modified).

Unfortunately one of my routes don't want to automatically infer the route type:

[esg]: src/pages/suppliers/[id].vue(6,59): error TS18046: '__VLS_ctx.route' is of type 'unknown'.
[esg]: src/pages/suppliers/[id].vue(8,76): error TS18046: '__VLS_ctx.route' is of type 'unknown'.
[esg]: src/pages/suppliers/[id].vue(18,16): error TS18046: 'route' is of type 'unknown'.
typed-router.d.ts
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.

declare module 'vue-router/auto-routes' {
  import type {
    RouteRecordInfo,
    ParamValue,
    ParamValueOneOrMore,
    ParamValueZeroOrMore,
    ParamValueZeroOrOne,
  } from 'vue-router'

  /**
   * Route name map generated by unplugin-vue-router
   */
  export interface RouteNamedMap {
    '/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
    '/suppliers/[id]': RouteRecordInfo<'/suppliers/[id]', '/suppliers/:id', { id: ParamValue<true> }, { id: ParamValue<false> }, '/suppliers/[id]/results/[[version]]'>,
    '/suppliers/[id]/results/[[version]]': RouteRecordInfo<'/suppliers/[id]/results/[[version]]', '/suppliers/:id/results/:version?', { id: ParamValue<true>, version?: ParamValueZeroOrOne<true> }, { id: ParamValue<false>, version?: ParamValueZeroOrOne<false> }>,
  }

  /**
   * Route file to route info map by unplugin-vue-router.
   * Used by the volar plugin to automatically type useRoute()
   *
   * Each key is a file path relative to the project root with 2 properties:
   * - routes: union of route names of the possible routes when in this page (passed to useRoute<...>())
   * - views: names of nested views (can be passed to <RouterView name="...">)
   *
   * @internal
   */
  export interface _RouteFileInfoMap {
    'src/pages/index.vue': {
      routes: '/'
      views: never
    }
    'src/pages/suppliers/[id].vue': {
      routes: '/suppliers/[id]' | '/suppliers/[id]/results/[[version]]' | '/suppliers/[id]/results'
      views: 'default'
    }
    'src/pages/suppliers/[id]/results/[[version]].vue': {
      routes: '/suppliers/[id]/results/[[version]]'
      views: never
    }
  }

  /**
   * Get a union of possible route names in a certain route component file.
   * Used by the volar plugin to automatically type useRoute()
   *
   * @internal
   */
  export type _RouteNamesForFilePath<FilePath extends string> =
    _RouteFileInfoMap extends Record<FilePath, infer Info>
      ? Info['routes']
      : keyof RouteNamedMap
}

Debugging

Reproduction: https://github.com/darkbasic/unplugin-vue-router-609

Steps:

  1. Clone and install repo
  2. Go to src/pages/suppliers/[id].vue
  3. See TS error 'route' is of type 'unknown'.

Findings

When updating [id].vue to this, the problem becomes clearer:

<template>
  <div>Test</div>
</template>
<script setup lang="ts">
  const route = useRoute()
  console.log(route.params.id)

  // eslint-disable-next-line @typescript-eslint/consistent-type-imports
  type RouteNamesForThisFilePath = import('vue-router/auto-routes')._RouteNamesForFilePath<'src/pages/suppliers/[id].vue'>;
  //    ^ "/suppliers/[id]" | "/suppliers/[id]/results/[[version]]" | "/suppliers/[id]/results"
  const route2 = useRoute<RouteNamesForThisFilePath>();
  //                       ^ Type '"/suppliers/[id]" | "/suppliers/[id]/results/[[version]]" | "/suppliers/[id]/results"' does not satisfy the constraint 'keyof RouteNamedMap'.
//                           Type '"/suppliers/[id]/results"' is not assignable to type 'keyof RouteNamedMap'.
</script>

While routes with names /suppliers/[id] and /suppliers/[id]/results/[[version]] do indeed exist, /suppliers/[id]/results does not.

@posva Any idea how a non-existing route name has ended up in here?

Metadata

Metadata

Assignees

No one assigned

    Labels

    ♦️ need reprothe issue needs a reproduction for further investigation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions