Skip to content

Commit 1aa0ea1

Browse files
committed
docs: add typed routes
1 parent 8b3faa9 commit 1aa0ea1

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

packages/docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ const config = defineConfig({
174174
text: 'Lazy Loading Routes',
175175
link: '/guide/advanced/lazy-loading.html',
176176
},
177+
{
178+
text: 'Typed Routes',
179+
link: '/guide/advanced/typed-routes.html',
180+
},
177181
{
178182
text: 'Extending RouterLink',
179183
link: '/guide/advanced/extending-router-link.html',
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Typed routes (v4.1.0+)
2+
3+
> ⚠️ This feature is still experimental and will evolve in the future
4+
5+
With typed routes you get type validation when calling `router.push()` as well as autocompletion for the route path. It gives you:
6+
7+
- Validation for [named routes](../essentials/named-routes.md) `name` and `params` properties
8+
- Autocompletion of the `to` prop when using the `<RouterLink>` component
9+
10+
## Usage
11+
12+
In order to benefit from typed routes, it is necessary to pass the `routes` option to the `as const`:
13+
14+
```ts{6}
15+
const router = createRouter({
16+
// ...
17+
routes: [
18+
{ path: '/', name: 'home' },
19+
{ path: '/users/:id', name: 'user' },
20+
] as const, // <-- this is the important part
21+
})
22+
```
23+
24+
This will give you a **typed router instance**. Go ahead and give it a try, start typing `router.push({ name: '|'}` and hit `ctrl` + `space` to autocomplete the route name. It will also autocomplete `params` if they exist and **give you a type error** if the name doesn't exist or if the provided params are missing any required params. Note that you can push a route **with no `params` property** and this will be considered valid for the types because `params` are always kept from the current route whenever possible.
25+
26+
### Typed `router` instance
27+
28+
It is possible to type `$router` and `useRouter()` to be the same type as the `router` instance we created above. To do this, we need to extend an interface. It's recommended to do so in the `router.ts` file, right after creating the router:
29+
30+
```ts{5-9}
31+
export const router = createRouter({
32+
// ...options
33+
})
34+
35+
declare module 'vue-router' {
36+
interface Config {
37+
Router: typeof router
38+
}
39+
}
40+
```
41+
42+
### Typed `<RouterLink>`
43+
44+
It's also possible to type the `to` prop of `<RouterLink>` by overriding the global type used by Vue. You can add this in the `router.ts` file, right after the previous snippet of code:
45+
46+
```ts{1,9-13}
47+
import type { RouterLinkTyped } from 'vue-router'
48+
49+
export const router = createRouter({
50+
// ...options
51+
})
52+
53+
// other code
54+
55+
declare module 'vue' {
56+
interface GlobalComponents {
57+
RouterLink: RouterLinkTyped<typeof router>
58+
}
59+
}
60+
```
61+
62+
## Caveats
63+
64+
Currently, typed routes are inferred at runtime with complex, costly types that become slow if you have a lot of routes. If you have more than 50 routes, you will should give this a try first to see how much it impacts the compilation time of your project.
65+
66+
If you have [dynamic routes](../advanced/dynamic-routing.md), these cannot be typed and if you use [named routes](../essentials/named-routes.md), you won't be able to push to them so it's better not to use both at the same time.
67+
68+
## Troubleshooting
69+
70+
If you ever find something blocking you or making your types too slow, you can just remove the `as const` part to rollback to the previous version of the types. If something not mentioned here isn't working and you think it sohuld be working, please open an issue on [GitHub](https://github.com/vuejs/router/issues).

0 commit comments

Comments
 (0)