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