Help us understand the problem. What is going on with this article?

Nuxt.js(+Vuex)にTypeScriptを段階的に導入する

とあるNuxt.jsプロジェクトにTypeScriptを段階的に導入しているので、その流れなどをここに書いておく。

サンプルとして簡単なTODOアプリをGitHubに置いてある。
https://github.com/hareku/nuxtjs-typescript-example

TypeScriptの導入

https://ja.nuxtjs.org/guide/typescript/

公式ドキュメントにも書いてあるがTypeScriptの導入は割と簡単にできる。

  1. yarn add -D @nuxt/typescript ts-node
  2. tsconfig.jsonという空ファイルをプロジェクトのルートディレクトリに作成
  3. yarn run devすると、自動でtsconfig.jsonの中身を書いてくれる

@nuxt/typescriptはNuxt.js用のtsconfig.jsonを生成するもので、ts-nodeはTypeScriptのファイルをトランスパイルせずに直接実行するためのもの。ESLintを使ってる人は他にもやることあるので、上の公式ドキュメントを見て欲しい。

型定義ファイルの追加

tsconfig.jsonで以下のように@nuxt/vue-appを読み込んでいるが、これはNuxt.jsが公式で用意しているNuxt関連の型定義ファイルだ。
https://github.com/nuxt/nuxt.js/tree/v2.8.0/packages/vue-app/types

tsconfig.json
{
  "compilerOptions": {
    "types": [
      "@types/node",
      "@nuxt/vue-app"
    ]
  }
}

ここでasyncDataの型などを定義しているのだが、vuex周りやaxiosモジュールなどを追加したい場合はこちらを使えない。そのため上記のtypesディレクトリを、nuxtというディレクトリ名に変えてプロジェクトのルートディレクトリにコピペする。

そして@nuxt/vue-appから./types/nuxtに変えておく。

Axiosモジュールの追加

Nuxt.jsではAxiosモジュールを導入することが多い。そのAxiosの型推論を効かせたい場合は、先ほど追加したtypes/nuxt/index.d.tsのContextに以下を追加する。

index.d.ts
import { NuxtAxiosInstance } from "@nuxtjs/axios"

export interface Context {
  // ...
  $axios: NuxtAxiosInstance
}

これでasyncDataなどの引数から$axiosを型推論付きで呼び出すことができる。

デコレータは使わない

Vue.jsではkaorun343/vue-property-decoratorというクラスとデコレータを使った型推論をする人が多かった。しかしデコレータの理解や、Vue公式ドキュメントに書かれている従来の書き方から離れているため、少し高いハードルがある。
このクラス方式も公式がVue3.0から用意しようとしていたが、取り消しになったようだ。
[Abandoned] Class API proposal by yyx990803 · Pull Request #17 · vuejs/rfcs · GitHub

そのため、vue-property-decoratorを使わず、普通にVue.Extendを使ってTypeScriptを扱うのが現状ベストなような気がする。Vue3.0への移行も簡単になるし、何より書き方をTypeScript導入前とほとんど変えずにできるのが良い。

ちなみにVue.Extendの場合はMixinにあるメソッドなどの推論が効かない。これに関してはVue3.0に期待だが…、今はMixinは使わないという方針にした。Mixinはな、あれは麻薬じゃ。書いている時は気持ち良いかも知れんが、可読性が著しく下がる。自分もVuexのMapを駆使したMixinを作っていたが、今は反省している。Mixinは辞めよう。

Vuexの型推論

Vuexが公式で用意している型ファイルでは型推論が十分ではない。そのため独自の型定義ファイルを用意する。

Vuexの型定義ファイルに関してはこちらのリポジトリを参考にした。
https://github.com/takefumi-yoshii/ts-nuxtjs-express

これによって以下のようにdispatchやcommit関数で渡す引数をすべて推論することができる。

vuex-typescript.png

各Storeモジュールごとに以下のように型定義ファイルを書く必要がある。

store/todo/type.ts
import { TODO } from '~/types/todo'

export interface S {
  list: TODO[]
}

export interface G {}
export interface RG {}

export interface M {
  setList: { todos: TODO[] }
}
export interface RM {
  'todos/setList': M['setList']
}

export interface A {
  fetchList: { limit: number }
}
export interface RA {
  'todos/fetchList': A['fetchList']
}

this.$storevuex側ですでに定義されてしまっているため、プラグインとして他の変数でVuexを参照できるようにしている。
このやり方はNuxtでデコレーターを使わずTypeScriptを書いてみた | MixDesignを参考にした。

plugins/ex-store.ts
export default (context, inject) => {
  const store = new ExStore(context.store)

  inject('state', store.state())
  inject('getters', store.getters())
  inject('commit', store.commit())
  inject('dispatch', store.dispatch())
}

// 各componentからはthis.$stateやthis.$dispatchで呼び出せる

ちなみにTypeScriptをvuexに導入する際に、すべてのモジュールを書き換える必要はない。推論を効かせたいモジュールのみTypeScriptで書いて、他のJSのモジュールはそのままthis.$storeから呼び出せるので共存できる。

まとめ

  • TypeScriptはVuexにも段階的に導入できるよ
  • vue-property-decoratorを使わなくても十分TypeScriptは運用できるよ
  • Mixinは使わない方針に

冒頭でも紹介したが、簡単なサンプルとしてTODOアプリをGitHubに置いてあるので参考に。
https://github.com/hareku/nuxtjs-typescript-example

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした