Typed Routes
This plugin generates a d.ts
file with all the typing overrides when the dev or build server is ran. Make sure to include it in your tsconfig.json
's (or jsconfig.json
's) include
or files
property:
{
// ...
"include": [
/* ... */
"./typed-router.d.ts",
]
// ...
}
The generated Route Map is picked up by unplugin-vue-router/client
types and configures the vue-router
types to be aware of the routes in your application. Making everything type safe!
TIP
You can commit the newly added .d.ts
files to your repository to make your life easier.
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
router.push('')
Extra types
typed-router.d.ts
contents
You can always take a look at the generated typed-router.d.ts
file to inspect what are the generated types. unplugin-vue-router
creates and exports a couple of types, among them, RouteNamedMap
with all the route records, typed, in your application. Each route record contains the route's name, path, typed params and a list of its child route names.
Other types, prefixed with an underscore (_
), are used internally, e.g. _RouteFileInfoMap
by the sfc-typed-router
Volar plugin to enhance typings for useRoute()
and $route
, if enabled, and are not meant to be used directly.
Manually typing dynamically added routes
The RouteNamedMap
interface contains all the routes in your application along with their metadata. You can augment it to add types for dynamic routes that are added during runtime.
import type { RouteNamedMap } from 'vue-router/auto-routes'
Note that, if you are using the sfc-typed-router
Volar plugin, you should also augment the _RouteFileInfoMap
interface for every dynamically added route corresponding to a page component.
export {} // needed in .d.ts files
declare module 'vue-router/auto-routes' {
import type {
RouteRecordInfo,
ParamValue,
// these are other param helper types
ParamValueOneOrMore,
ParamValueZeroOrMore,
ParamValueZeroOrOne,
} from 'vue-router'
export interface RouteNamedMap {
// the key is the name and should match the first generic of RouteRecordInfo
'custom-dynamic-name': RouteRecordInfo<
'custom-dynamic-name',
'/added-during-runtime/[...path]',
// these are the raw param types (accept numbers, strings, booleans, etc)
{ path: ParamValue<true> },
// these are the normalized params as found in useRoute().params
{ path: ParamValue<false> },
// this is a union of all children route names
// if the route does not have nested routes, pass `never` or omit this generic entirely
| 'custom-dynamic-child-name'
>
'custom-dynamic-child-name': RouteRecordInfo<
'custom-dynamic-child-name',
'/added-during-runtime/[...path]/child',
{ path: ParamValue<true> },
{ path: ParamValue<false> },
| never
>
}
export interface _RouteFileInfoMap {
// the key is the file path and should match the page component's file path
'/added-during-runtime/[...path].vue': {
// these are the route names that can be displayed within this component
routes: 'custom-dynamic-name' | 'custom-dynamic-child-name'
// these are the views that can be used in this file
views: 'default'
}
'/added-during-runtime/[...path]/child.vue': {
routes: 'custom-dynamic-child-name'
views: never
}
}
}
You can now pass a type param to the generic route location types to narrow down the type of the route. This automatically includes any child routes typings as well:
// These are all valid ways to get a typed route and return the
// provided route's and any of its child routes' typings.
// Note that `/users/[id]/edit` is a child route
// of `/users/[id]` in this example.
// Not recommended, since this leaves out any child routes' typings.
const userRouteWithIdCasted =
useRoute() as RouteLocationNormalizedLoaded<'/users/[id]'>
userRouteWithIdCasted.params.id
// Better way. Includes child routes' typings, but no autocompletion.
const userRouteWithIdTypeParam = useRoute<'/users/[id]'>()
userRouteWithIdTypeParam.params.id
// 👇 This one is the easiest to write because it both
// autocompletes and includes child routes' typings.
const userRouteWithIdParam = useRoute('/users/[id]')
userRouteWithIdParam.name
userRouteWithIdParam.params.id
Using the sfc-typed-router
Volar plugin
This Volar plugin automatically types useRoute()
and $route
correctly in page components, so you don't have to write code like useRoute('/users/[id]')
, allowing you to write less code.
To start using the plugin, add the following to the tsconfig.json
file that includes your Vue files:
{
// ...
"vueCompilerOptions": {
"plugins": ["unplugin-vue-router/volar/sfc-typed-router"]
}
}
As long as this plugin isn't enabled in Nuxt by default with experimental.typedPages: true
or through any other experimental feature flag, you should manually add the plugin via nuxt.config.ts
:
export default defineNuxtConfig({
// ...
typescript: {
tsConfig: {
vueCompilerOptions: {
plugins: ['unplugin-vue-router/volar/sfc-typed-router'],
},
},
},
})
When using the sfc-typed-router
Volar plugin, useRoute()
and $route
are typed automatically for page components under the hood, so you don't have to do it manually.