TypeScriptのプロジェクトでESLint+Prettierを活用する
コーディングスタイルに一貫性をもたせことは重要であると広く認識されています。
- プロジェクト全体でEnumの使用を禁止する
- 関数内でのthisを禁止する
- インデントにはスペースを使う
- セミコロンは必要でない場合省略する
上記の様なコーディングスタイルはプロジェクトの考え方によって異なると思います。複数人が関わるプロジェクトではルールを明文化していたとしてもコードに一貫性をもたせるのは難しいですし、個人のプロジェクトであってもルールを一貫させるには少なからず苦労します。
そんな問題を解決する為にTypeScriptにはTSLintというリンターが広く使われていましたが、2019年に非推奨とされました。今はJavaScriptのリンターであるESLintにTypeScriptのプラグインを合わせて使うことが推奨されています。
この記事ではTypeScriptプロジェクトでESLint+Prettierを使う際の個人的な基本コードを解説しています。
前提
- node.jsがインストールされている
- TypeScriptのインストールと設定ファイルの作成済み
上記の前提で説明しています。また、記事執筆時のバージョンは下記の様になります。node : 12.18.3 typescript : 3.9.3 eslint : 7.4.0 prettier : 2.0.5
ESLintの導入
設定の記述
まず、ESLintとESLintがTypeScriptを理解する為に必要なプラグインをインストールします。
npm i -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser
インストールが完了したらESLintの設定を記述する.eslintrc.js
ファイルをプロジェクトのルートに作成し、以下の様に記述します。
module.exports = { root: true, // .eslintrc.jsがプロジェクトのルートに配置させているか(指定がないと上位階層へ設定ファイルを探索される) parser: '@typescript-eslint/parser', // ESLintにTypeScriptを理解させる parserOptions: { project: './tsconfig.json' // tsconfig.jsonの場所を指定 }, plugins: [ '@typescript-eslint' // ESLintのTypeScriptプラグインのルールを適用できる様にする(/eslint-pluginは省略可) ], extends: [ 'eslint:recommended', // ESLintのJavaScriptルールセットを適用 'plugin:@typescript-eslint/eslint-recommended', // eslint:recommendedに含まれるルールを型チェックでカバーできるものは無効化 'plugin:@typescript-eslint/recommended', // 型チェックが不要なルールを適用 'plugin:@typescript-eslint/recommended-requiring-type-checking', // 型チェックが必要なルールを適用 ] }
extends
の部分を簡単に補足すると、ESLintお勧めのルールセット(JavaScript用のルール)をベースで読み込んで、さらにTypeScript用にプラグインを使ってルールの上書きをしています。
.eslintrc.js
が用意できたら、package.jsonに実行用のsctiptを追記します。
"scripts": { "lint": "eslint . --ext ts" }
上記の記述でプロジェクト内の/node_modulesを除く全てのファイルにLintを実行することができます。
Lintの実行
試しに用意したtsファイルにLintを実行してみます。
export class Person { constructor(public name: string, public age: number) { } public greeting(this: Person) { document.write(`私の名前は${this.name}です。 年齢は${this.age}歳です。`); } }
npm run lint
を実行すると...
5:3 warning Missing return type on function
greeting
メソッドの返り値に型が指定されていないと注意してくれました。
export class Person { constructor(public name: string, public age: number) { } public greeting(this: Person): void { document.write(`私の名前は${this.name}です。 年齢は${this.age}歳です。`); } }
返り値を指定して再度Lintを実行すると警告は消えました。
自動修正をするためにPrettierを導入
設定の記述
エラーを教えてくれるだけでは不親切なので、自動でコードフォーマットしてくれるPrettierをインストールしましょう。
npm i -D prettier eslint-config-prettier eslint-plugin-prettier
インストールできたら.eslintrc.js
に下記を追加で記述します。
plugins: [ //.... 'prettier' ], extends: [ //.... 'prettier/@typescript-eslint', // Prettierでカバーできるルールを無効化 'plugin:prettier/recommended' // Prettierのお勧めルールセットを適用 ]
新たに.prettierrc.js
をプロジェクトのルートに作成します。
module.exports = { 'singleQuote': true, // singleQuoteを有効 'semi': false, // セミコロンを禁止 'no-extra-semi': 'error', // 余分なセミコロンを禁止 'no-unexpected-multiline': 'error', // 意図に反して2つの文が接続された箇所を警告 }
さらに、package.jsonの実行用のsctiptを下記の様に修正して、自動で修正できるように変更します。
"scripts": { "lint": "eslint . --ext ts --fix" }
Lintの実行
先ほどLintを実行したサンプルのtsファイルに再度Lintを実行してみます。
export class Person { constructor(public name: string, public age: number) { } public greeting(this: Person): void { document.write(`私の名前は${this.name}です。 年齢は${this.age}歳です。`); } }
npm run lint
を実行すると...
export class Person { constructor(public name: string, public age: number) {} public greeting(this: Person): void { document.write(`私の名前は${this.name}です。 年齢は${this.age}歳です。`) } }
Prettierがフォーマット可能な修正に限り自動で修正してくれます。
今回だと必要のないセミコロンが削除され、constructorの波かっこの改行が消されていますね。
おまけ
VSCodeにはESLintの拡張機能があります。
https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
この記事で説明したPrettierの設定がされている状態でESLint拡張機能を有効化しておけば、ファイル保存時に自動でコードフォーマットしてくれる為さらに便利です。