🐕‍🦺

Nuxt.jsで、型安全にrouterを扱うモジュール[Nuxt Typed Router]の使い方

2023/12/21に公開

はじめに

useRouterを使って、router.push()で、間違えて存在しないパスを指定したり、パス構成を忘れて、わざわざパス構成を確認してしまう。。
ということはありませんか?

今回は、そんなミスや手間を省くことができる、「Nuxt Typed Router」というモジュールを紹介します。

このモジュールは、型安全にrouterを使うことができるモジュールです。
今後も使えそうな、良さげなモジュールでした!

元々はpathpidaを使おうと思ったのですが、どうやらVue2/Nuxt2系対応のようで、Nuxt3ではうまくいかず。。こちらを見つけました。

公式はこちら↓
https://nuxt-typed-router.vercel.app/

このモジュールを使って得られること

  • パスを指定するとき、型補完が効く
  • 存在しないパスを設定したら、エラーを出してくれる

例えば、こんな感じになります。

存在しないパスを指定すると、怒られます。

モジュールの仕組み

NuxtのuseRouter / useRoute / navigate / NuxtLinkなどに対して、アプリケーションのパスの構成に応じて型を自動生成してくれます。

例えば、Nuxt3アプリケーションのpagesフォルダの配下が、以下の状態の場合どうなるか説明しますね。

/pages
	L news
	   L index.vue
	   L detail
	      L [id].vue
	L about
	   L index.vue

自動生成後は、router.push()の引数で、

  • /news
  • /news/detail:id
  • /about
    以外のパスを指定すると、エラーが出るようになります。

実際に使ってみる

導入

インストール

npm install nuxt-typed-router

nuxt.config.tsにモジュール登録

export default defineNuxtConfig({
  modules: [
    'nuxt-typed-router',
  ]
})

型の自動生成

導入後、npm run dev・npm run buildなどをすると、pagesの構成を見て型を生成してくれます。
以下が出たら、型が生成されたということです。

router.pushを使ってみる

router.pushで、補完が効いてます。存在しないパスを設定すると、エラーが出ます。
※案件の内容になるので、補完部分隠してます。

route.paramsを使ってみる

routeはちょっとコツが要ります。
存在しないパスパラメーターにアクセスすると型エラーが出てしまうので、型ガードをする必要があります。

<script setup lang='ts'>

const route = useRoute();

console.log(route.params.foo);
// fooが存在しないパスもあるので、エラーが出る。

if (route.name === 'foo') { 
  console.log(route.params.foo) // これであれば、エラーがでない。
}
</script>

別の方法

useRouteの引数に、パス or 自動生成されたパス名を設定すると、設定したパス名のrouteになるので、型ガードの必要がありません。

<script setup lang='ts'>

const route = useRoute('admin-id'); // パス名を指定してuseRouteを使う

console.log(route.params.id) // adminにidというパラメーターがあるので、エラーが出ない。
</script>

コンポーネントを作る場合

UIライブラリのボタンコンポーネントに、toやhrefなどのpropsでリンク設定すること結構ありますよね。

Nuxt Typed Routerは、流石にUIライブラリのボタンコンポーネントのリンクのpropsの型を上書きしてくれないので、自作する必要があります。

結論から言うと、以下のような感じです。VuetifyのVBtnを例に挙げてます。

<template>
  <VBtn :to="props.to">
    <slot />
  </VBtn>
</template>

<script setup lang="ts" generic="T extends RoutesNamesList, P extends string">
import type { RoutesNamesList, NuxtRoute } from '@typed-router';

interface Props {
  to: NuxtRoute<T, P>;
}
const props = defineProps<Props>();
</script>

公式にやり方が書いてありました
URL: https://nuxt-typed-router.vercel.app/usage/typing-components

ポイントとしては、

  • scriptタグに、genericで型引数を設定(propsのtoに入力されたの容によって、propsのtoの型が変わる)
  • 一回const propsに受けてから、VBtnにtoを設定しないと、VBtnのtoのところで怒られる。(なぜこうなるかはわからん)
    と言う感じです。

自動生成した型たちを使う

@typed-routerというエイリアスから、Nuxt Typed Routerが生成してくれた型をimportして使うことができます。

以下のような感じ

import type { RoutesNamesList, RoutesParamsRecord } from '@typed-router';

importできる型は以下に書いてあります。
https://nuxt-typed-router.vercel.app/api/types

ヘルパー関数で、存在するパスかどうかチェックする

helpers.path

import {helpers} from '@typed-router';
const route = helpers.path('/news') // 存在しないパスならエラーが出る

helpers.route

import {helpers} from '@typed-router';
const route = helpers.route({name: 'admin-id'}) // 存在しないパス名ならエラーが出る

参考: https://nuxt-typed-router.vercel.app/usage/helpers

終わりに

プロジェクト始めるタイミングで、こちらを入れると、型安全に画面遷移・パラメーター取得ができるようになって、ミスが減って良いと思います。

参考
https://nuxt-typed-router.vercel.app/

Discussion