Nuxt.jsをはじめよう - TypeScriptでコードを書く
前回の記事 では Vuex を使った状態管理の仕方を書きました。 今回はNuxt.jsのコードをTypeScriptで書くための設定や書き方などを紹介します。
なお、ここでは Nuxt 2.8.x を想定しています。
Nuxt.jsのTypeScriptサポート
Nuxt.js ではTypeScriptをサポートしています。JavaScriptを使った開発において、TypeScriptは静的な型付けをしてくれる言語であるため潜在的なエラーをコーディング段階で排除できることから人気があります。
公式でもTypeScriptのサポートを謳って おり、今回はそれを参考にしつつTypeScriptへの書き換えを行っていきましょう。
なお、2019/08現在では npx create-nuxt-app
コマンドを通じてTypeScriptプロジェクトを生成することはできないので、手動で設定を追加していく必要があります。
TypeScriptのモジュールインストール
まずはTypeScriptをトランスパイルするためにモジュールをインストールします。
1npm i -D @nuxt/typescript
2npm i ts-node
3npm i -S vue-property-decorator
vue-property-decorator は公式から提供されたモジュールではないのですが、Nuxt.jsの公式が使うことを推奨しているモジュールのためインストールしておきます。このモジュールにより、.vue
ファイルの <script>
ブロックをよりClassっぽく書くことができます。
Configファイルの書き換え
次に、プロジェクトルートに tsconfig.json
ファイルを作成します。
既にファイルが存在する場合は省略して構いません。
1touch tsconfig.json
次にプロジェクトルートにある nuxt.config.js
を nuxt.config.ts
にリネームを行います。
1mv nuxt.config.js nuxt.config.ts
その後、nuxt.config.ts
の内で NuxtConfiguration
型の定数をexportしてあげます。この config
の中に nuxt.config.js
の中身をそのままコピーしてあげれば良いです。
1import NuxtConfiguration from '@nuxt/config'
2
3const config: NuxtConfiguration = {
4// ここに中身を引っ越す
5}
6export default config;
Vueコンポーネントの書き換え
次にVueコンポーネントを書き換えます。まずは <script>
ブロックに lang="ts"
を追加してTypeScriptであることを教えてあげます。
1<script lang="ts">
次にClassを実装してexportします。ざっくりサンプルを記載します。 以下のコードではTypeScript化にしたことでスッキリした点を記載します。
@Component(components:〜)
によって依存するVueコンポーネントを完結に記載できる<template>
ブロック内で呼び出す関数はClass内の関数として定義できる- 依存する
Vuex
ストアも明示的にimportするので理解しやすい - TypeSafeな実装にすることができる
1<template>
2 <div class="container">
3 <div class="columns">
4 <Monitor />
5 <Menu />
6 </div>
7 <Msg :message="initMsg" />
8 <div class="buttons are-medium">
9 <a class="button is-primary is-outlined" @click="regist('A')" >A</a>
10 <a class="button is-link is-outlined" @click="regist('B')">B</a>
11 <a class="button is-info is-outlined" @click="regist('C')">C</a>
12 </div>
13 </div>
14</template>
15
16<script lang="ts">
17import { Vue, Component } from 'vue-property-decorator'
18import { userModule } from '@/store/modules/user'
19
20@Component({
21 components: {
22 Monitor: () => import('../components/Monitor.vue'),
23 Menu: () => import('../components/Menu.vue'),
24 Msg: () => import('../components/Msg.vue')
25 }
26})
27export default class Next extends Vue {
28 initMsg: string = 'Welcome to netx page!!'
29
30 public async regist(value) {
31 await userModule.save()
32 this.$router.push('/users/')
33 }
34}
35</script>
注意点としては、@Component
アノテーションの中では computed
や methods
といったパラメータも受け付けられるので、アノテーション中に処理をモリモリ書いていくとTypeScriptにした旨味が減るように思います。
若干学習コストを払いますが vue-property-decoratorのdoc を読みながらClassで書く方法を模索すると良いです。
最後にStoreのコードもTypeScript化してみます。ここでは vuex-module-decorators を使って書いていますが、このモジュールはvue-property-decorator と違ってNuxt.jsの公式から推奨されているわけではないので、利用するかどうかはおまかせします。
1import { VuexModule, Module, Action, Mutation, getModule,} from 'vuex-module-decorators';
2import store from "@/store/store"
3import axios from 'axios';
4
5export interface User {
6 name: string
7}
8
9interface UserState {
10 users: Array<User>;
11}
12
13@Module({ dynamic: true, store, namespaced: true, name: 'user'})
14class UserModule extends VuexModule implements UserState {
15
16 users: Array<User> = [];
17
18 get all(): Array<User> {
19 return this.users;
20 }
21
22 @Mutation
23 updateUser(users: Array<User>): void {
24 this.users = users
25 }
26
27 @Action({})
28 async save() {
29 const users = await axios.get<Array<User>>(process.env.apiBaseUrl + '/users')
30 this.updateUser(users.data)
31 }
32}
33export const userModule = getModule(UserModule)