🚦Typed Router Module
Provide a safe typed router to nuxt with auto-generated typed definitions for route names
Motivation
Nuxt is great because it generate the router based on your pages directory. It generates all the pages name and it abstract a lot of boilerplate.
Problem: If you want a type-safe routing flow, the current model can be hard to maintain if you modify the page file name and is error prone in big projects.
Solution: Thanks to Nuxt powerful hook system, this module reads all your routes and generate typings and enums accordingly
Installation
yarn add nuxt-typed-router
npm install nuxt-typed-router
Configuration
First, register the module in the nuxt.config.[js|ts]
const config = {
...,
modules: [
'nuxt-typed-router',
]
}
Or
const config = {
...,
modules: [
['nuxt-typed-router', {
}],
]
}
Usage in Vue/Nuxt
Nuxt-typed-router provides two ways to have name-based typed routing
- $typedRouter
(Default)
A global $typedRouter
method is added to the Nuxt context and is accessible in your components and context. It's an alias of Vue $router
, but the typings are modified so the name
options is typed with the routes names generated from the pages directory
Why not directly modifying the types of $router
and $route
?
That was the idea when I builded this module initially, but I got confronted with Typescript limitations for modifying already defined third-party lib typings.
If I wanted to modify vue-router types, i could have just written this:
declare module 'vue-router/types' {
export interface Location {
name: 'login' | 'home';
}
}
Unfortunately that's not possible, Typescript throws this errors:
-
Subsequent property declarations must have the same type. Property 'name' must be of type 'string', but here has type '"login" | "home"
-
All declarations of 'name' must have identical modifiers
So the only way for now is to have an alternative $typedRouter
, or a global enum-like object.
Requirements
For your IDE to augment the Vue types, you need to explicitly import the module in your Nuxt config
import 'nuxt-typed-router';
Usage
The usage is exactly the same as $router
Given this structure
├── pages
├── index
├── content.vue
├── index.vue
├── communication.vue
├── statistics.vue
├── users.vue
├── index.vue
├── forgotpassword.vue
├── reset-password.vue
│ └── login.vue
└── ...
This module also provide $typedRoute
, wich is an alias to Vue $route
, but with typed name property
Caveats
The generated enum is located in the node_modules
folder.
Because of Intellisense limitations, the types from node_modules are not lived updated, so you need to either reload the window or restart Intellisense when you add a Page/ modify the name of a Page for it to take into account the pages names freshly generated
- routerPagesNames
global object
The module will create a file with the global object of the route names inside.
Requirements
You have to specify the path of the generated file in your configuration
const config = {
typedRouter: {
filePath: './models/__routes.js',
},
};
const config = {
modules: [
[
'nuxt-typed-router',
{
filePath: './models/__routes.js',
},
],
],
};
Usage
Given this structure
├── pages
├── index
├── content.vue
├── index.vue
├── communication.vue
├── statistics.vue
├── users.vue
├── index.vue
├── forgotpassword.vue
├── reset-password.vue
│ └── login.vue
└── ...
The generated file will look like this
export const routerPagesNames = {
forgotpassword: 'forgotpassword',
login: 'login',
resetPassword: 'reset-password',
index: {
index: 'index',
indexCommunication: 'index-communication',
indexContent: 'index-content',
indexStatistics: 'index-statistics',
indexUsers: 'index-users',
},
};
You can just import it now
import { routerPagesNames } from '~/models/__routes.js';
export default {
mounted() {
this.$router.push({ name: routerPagesNames.index.indexContent });
},
};
Development
- Clone this repository
- Install dependencies using
yarn
or npm install
📑 License
MIT License