Vue + TypeScriptなプロジェクトにESLintを導入する

TypeScript + VueなプロジェクトでESLintを使ってみて、現状必要なモジュールが複数あって少し複雑だったのでまとめておきます。

サンプルは以下です。 github.com

内容はどうでも良いんですが、こんな感じのすごく簡単なTODO風のアプリケーションです。 f:id:joe-re:20180102214723p:plain

なぜEslintを使うか

JavaScriptのためのLintingツールはたくさんありますが、Vueのroadmapにもある通り、Vueの公式スタイルガイドをサポートするESLintプラグインがESLintのメンテナによる公式プラグインとして作られています。

GitHub - vuejs/roadmap: Roadmap for the Vue.js project

これからもVueの公式としてサポートされていくと思うので、特にこだわりがなければESLintを使うのが良いかと思います。

ESLint for TypeScript

ESLintはJavaScript(ECMAScript)のためのLintingツールですが、TypeScriptをESTree互換の形に変換し、ESLintを適用できるようにするパーサがプラグインとして提供されています。TypeScriptのプロジェクトにESlintを使う場合にはこのプラグインが必要です。

github.com

以下のようにparserに指定すれば動きます。

.eslintrc.json

{
   "parser": "typescript-eslint-parser",
   "extends": [
    "eslint:recommended"
   ]
}

ただし、TypeScriptはもともとESTree互換ではないので、現在(v11.0.0)いくつかのルールが思うように動きません。

Discussion: Extending core ESLint rules to "just work" with TS-specific nodes · Issue #77 · eslint/typescript-eslint-parser · GitHub

eslint-plugin-typescriptというプラグインを使うと、TypeScriptの用のルールを導入することができます。

github.com

今回導入したプロジェクトも冒頭のサンプルもTypeScriptのみで構成されているので問題になりませんが、ピュアなJavaScriptと併用する場合にはルールがぶつかってしまうかもしれません。 ESLintは適用するルールをファイルタイプごとに設定ができるので、これを用いてJavaScriptとTypeScriptを分ければ回避できるはずです。

eslint.org

ESLint for Vue Single File Component

VueのSingleFileComponent(.vue)にESLintを適用するためのパーサを ESLintのメンテナのmysticateaさんが公開しています。

github.com

これを使うと、.vueファイルにESLintを適用することができます。 TypeScriptと併用する場合には、以下のようにparserOptionセクションにtypescript-eslint-parserを指定します。

.eslintrc.json

{
  "parser": "vue-eslint-parser",
  "parserOptions": {
    "parser": "typescript-eslint-parser"
  },
  "extends": [
    "eslint:recommended",
    "typescript"
  ]
}

サンプルを作った時点(2017/1/1)では、現状のstable(1.0.0)ではなくbetaをinstallする必要がありました。

mysticateaさんに教えていただきまして、現在はstableでokだそうです。

npm install vue-eslint-parser -D

Linting according to Vue StyleGuide

Vue.jsの公式として、ESLintプラグインが提供されています。

github.com

これは以下のStyle Guideを提供するための追加ルールと、ルールを組み合わせたテンプレートを提供しています。 vuejs.org

これにはテンプレート部分のシンタックスチェックも含まれるので、以下のようにテンプレート部分の違反を検出することができるようになります。