TypeScriptのプロジェクトにESLintとPrettierを導入する方法（+VSCodeでの設定）

ネット上に様々な方法で導入する方法が載っており、どれが良いのか分からなかったので自分なりにまとめてみました。
この記事は2020年8月時点での情報です。（2021/06/21 最新の情報を一部追記しました。）

## 内容
- 各種パッケージのインストール
    - TypeScriptとESLintのインストール
    - Prettierのインストール
- 動作確認
- VSCodeでの自動フォーマット設定
- （余談）eslint-plugin-prettierというプラグインの利用に関して

#### 環境
- typescript: 4.0.2
- eslint: 7.7.0
- @typescript-eslint/eslint-plugin: 3.10.1
- @typescript-eslint/parser: 3.10.1
- prettier: 2.1.1
- eslint-config-prettier: 6.11.0


## 各種パッケージのインストール
### TypeScriptとESLintのインストール
まず、[typescript-eslintのREADME.md](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/README.md)を参考に TypeScriptとESLintをインストールします。

```bash
$ npm i --save-dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin
```
TypeScriptとESLintの設定ファイルを生成します。ESLintに関しては、質問に答えていくと必要なnpmパッケージのインストールや設定ファイルを生成してくれます。とても便利です。

```bash
$ npx tsc --init
$ npx eslint --init
```
または、README.mdには必要最小限の設定が載っています。

```JavaScript:.eslintrc.js
module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  plugins: [
    '@typescript-eslint',
  ],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
};
```
※AirbnbのConfigを採用したい場合は[eslint-config-airbnb-typescript](https://www.npmjs.com/package/eslint-config-airbnb-typescript)を参照して設定する。

### Prettierのインストール
フォーマッタであるPrettierをインストールします。

```bash
$ npm install --save-dev prettier
```

Prettierのサイトの"[Integrating with Linters](https://prettier.io/docs/en/integrating-with-linters.html#disable-formatting-rules)"というページによると、ESLintのフォーマットに関するルールを無効化する（Prettierと競合する可能性があるので）ために、`eslint-config-prettier`というnpmパッケージをインストールします。

```bash
$ npm install --save-dev eslint-config-prettier
```

`.eslintrc.js`に設定を追加します。

```diff_javascript:.eslintrc.js

module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  plugins: [
    '@typescript-eslint',
  ],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
+    'prettier',
+    'prettier/@typescript-eslint', // eslint-config-prettierがv8.0.0以上の場合不要です
  ],
};
```
[eslint-config-prettierのページ](https://github.com/prettier/eslint-config-prettier#installation)に
> add eslint-config-prettier to the "extends" array in your .eslintrc.* file. Make sure to put it **last**, so it gets the chance to override other configs.

とあるように、extendsの一番最後に設定しましょう。

---
（2021/06/21 追記）
`eslint-config-prettier`がv8.0.0以上の場合、`extends`には`prettier`のみ設定してください。

> ℹ️ Note: You might find guides on the Internet saying you should also extend stuff like "prettier/react". Since version 8.0.0 of eslint-config-prettier, all you need to extend is "prettier"! That includes all plugins.
(https://github.com/prettier/eslint-config-prettier#installation)

---

次に、Prettierの設定ファイルを作成します。[こちらのページ](https://prettier.io/docs/en/configuration.html)を参考に作成しましょう。（以下は例）

```Javascript:.prettierrc.js
module.exports = {
  trailingComma: "es5",
  tabWidth: 4,
  semi: true,
  singleQuote: true,
};
```

## 動作確認
さて、ESLintとPrettierが正しくインストールできたか確認しましょう。

まず、動作確認用のファイル`index.ts`を作成します。

```index.ts
let text = "Hello, world"
```
ESLintによるチェックを行います。以下のようにESLintによるチェック結果が表示されます。

```bash
$ npx eslint index.ts

(任意)/index.ts
  1:5  warning  'text' is assigned a value but never used        @typescript-eslint/no-unused-vars
  1:5  error    'text' is never reassigned. Use 'const' instead  prefer-const

✖ 2 problems (1 error, 1 warning)
  1 error and 0 warnings potentially fixable with the `--fix` option.
```

次にPrettierの確認です。以下のようにPrettierによってフォーマットされる結果が表示されればOKです。

```bash
$ npx prettier  index.ts
let text = 'Hello, world';
```
※元のソースコードに対して、ダブルクォーテーションからシングルクォーテーションに変換され、末尾にセミコロンが追加されています。

以上でESLintとPrettierのインストールは完了です。

## VSCodeでの自動フォーマット設定
以下、VSCodeでESLintとPrettierを便利に利用するための設定を説明します。
VSCode以外のエディタに関する設定も公式サイトに案内があるので、その方は以下のサイトをご覧ください。

- https://eslint.org/docs/user-guide/integrations
- https://prettier.io/docs/en/editors.html

まず、ESLintとPrettierという拡張機能をインストールしてください。

https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint

https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode

次に、「ファイル」→「基本設定」→「設定」から設定を開きます。（または、`Ctrl + ,`で開きます。）
「ユーザー」または「ワークスペース」を選択し、右上にあるファイルマークをクリックして`settings.json`を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356779/dbb44227-8327-3590-8f8c-a5f306aaae32.png)

以下のように設定します。

```json:settings.json
{
    "[typescript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode" // フォーマッタをprettierに指定
    },
    "editor.formatOnSave": true, // ファイル保存時にPrettierでフォーマット
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true // ファイル保存時にESLintでフォーマット
    }
}
```

※`"editor.formatOnSave"`に関してはfalseにするブログ記事もありますが、後述する「eslint-plugin-prettier」というプラグインを利用した場合の設定です。

以上の設定をしたら、`index.ts`を開いて保存してください。以下のようにコードがフォーマットされるでしょう。

```typescript:index.ts
const text = 'Hello, world';
```
`let`から`const`に変換され（ESLintによるフォーマット）、末尾にセミコロンが追加されます。

以上で、VSCodeの自動フォーマット設定は完了です。

## 最後に
Linterやフォーマッタは開発を効率よく進めるために必要不可欠なツールです。しかし、その設定に時間を取られていては本末転倒ですし、毎回毎回調べるのが面倒だったので、記事にしてみました。

調べている最中に、Gitでコミットする前にPrettierのフォーマットをかけることができる方法もあると分かりました（[リンク](https://prettier.io/docs/en/precommit.html)）。エディタの設定をしていたはずなのに設定が漏れていてそのままコミットしてしまうことの予防策として導入するのがよさそうだと思いました。

この記事が（未来の自分）を含めてどなたかのお役に立てれば幸いです。


## （余談）eslint-plugin-prettierというプラグインの利用に関して
ネットでESLintとPrettierを導入する記事を探すと、`eslint-plugin-prettier`というプラグインを利用している記事がよく見つかります。ESLintによってPrettierを呼び出してフォーマットする方法です。
[Prettierのページ](https://prettier.io/docs/en/integrating-with-linters.html#notes)には「一般的には推奨しない。しかし、ある状況においては役立ちます。」と書いてありました。
> When searching for both Prettier and your linter on the Internet you’ll probably find more related projects. These are generally not recommended, but can be useful in certain circumstances.

Prettierができて間もないときはプラグインを利用する方法が良かったそうです。
役立つ状況がどんな状況なのかが私には分からないのですが、（一般的には）プラグインを使わない方法で進めると良いと思います。

やはりネットの記事を参考にするのも良いですが、公式のドキュメントを読むことが大事ですね。


## 参考サイト
https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/README.md

https://github.com/prettier/eslint-config-prettier#installation

https://prettier.io/docs/en/integrating-with-linters.html

https://www.npmjs.com/package/eslint-config-airbnb-typescript

https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint

https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode

https://qiita.com/soarflat/items/06377f3b96964964a65d