TypeScriptのLint

JavaScriptもTypeScriptも混じっているプロジェクトで、Lintのルールをなるべく共通化して運用したいというモチベーションがある。

JavaScriptのLinterはESLintを使いたい。TypeScriptのLinterはTSLintがデファクトだが、TSLintはESLintと比べて実装されているルールがだいぶ少なかったり、同じルールでも名前が違ったりする。

解決するアプローチは以下の二つがある。

typescript-eslint-parser

https://github.com/eslint/typescript-eslint-parser

ESLintのパーサーにTypeScriptを使うことでTypeScriptのLintをESLintで行う。JSもTSも同じ設定でいけるので最高便利。なんだけどREADMEに

Important: This parser is not fully compatible with all ESLint rules and plugins. Some rules will improperly mark source code as failing or not find problems where it should.

とあるように対応が不完全なところもあるのが難点。

現状で一番致命的なのは未定義の変数を検出するno-undefを有効にしていると、以下の箇所でエラーになるというバグもの。

class Foo {
  a: string; //=> error  'a' is not defined  no-undef

  constructor() {
    this.a = "a";
  }
}

ワークアラウンドな対応として、TypeScriptのときだけno-undefoffにすればいい。未定義な変数はTypeScriptのコンパイラで検出できるし。

overrides:
  files: ['**/*.ts', '**/*.tsx']
  parser: typescript-eslint-parser
  rules:
    no-undef: off

こういう感じで。

また、TypeScript specificなルールを使うには以下のようなプラグインがあるが、TSLintには及ばないので型情報が必要なLintはある程度諦めが必要になる。 https://github.com/nzakas/eslint-plugin-typescript

tslint-eslint-rules

https://github.com/buzinas/tslint-eslint-rules

もう一つがTSLintをESLintに寄せるためのモジュール。ESLintにあってTSLintにないルールを補完する*1。方向性としてはよいんだけど、現時点では対応していないルールもかなり多い。あと、TSLint本体のルールがESLintのルールと名前が違う問題は解決されない。

どっちを使うか

状況にもよると思うけどtypescript-eslint-parserを使ってESLintに寄せるようにした。ESLintとTSLintを併用しないで済むし、ESLintの豊富なルールも使える(使うかどうかは置いといて)ので、多少バグっていることを差し引いてもこちらのアプローチのほうが運用が楽そうだった。

*1:なんでTSLint本体にコントリビュートしないのかよくわからない