TypeScriptのLinterとしてESLintを導入してみる

# 背景
TypeScriptを使用する際にESLintを導入するお話がでた。
今まではコーディング規約だけ決定して、以降は各々の裁量でコーディングしていた部分があったため、この機に導入してみることにした。

# ESLintとは？
Javascriptコードの静的コード分析ツールです。
定義ファイルを編集することで細かいルールの調整を行うことができ、コーディング規約などを定義に使用できます。
複数人で開発する際にコーディングのスタイルを統一し、コードの一貫性を高めてバグを回避する役立ちます。

# 導入方法
## 環境
- Debian GNU/Linux 11

## 0. 実行前準備
以下のファイルを作成済みであること
- package.json (作成コマンド : npm init)
- tsconfig.json (作成コマンド : tsc --init)

## 1. eslintに必要なライブラリをインストールする
### インストールするライブラリ
- eslint : eslintライブラリ本体
- typescript-eslint/parser : ESLintにTypeScriptの構文を理解させるためのパッケージ
- typescript-eslint/eslint-plugin : TypeScript向けのルール追加を行うためのパッケージ
```
npm install -g eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin 
```

## 2. 設定ファイルの作成
以下のコマンドを実行し、eslintのルールを記載した定義ファイルを作成する。
```
npx eslint --init
```

上記のコマンドを実行すると以下に記載したような設問が問われます。設問に従って選択していくとeslintの設定ファイルの作成が完了します。
以下では私が使用する用に設定した一例記載します。

### 設問1 eslintで何をしたいですか？
今回は構文チェックと問題の発見、スタイルの強制まで実施してみます。
```
asuhi@Debian-Local:~/Documents/practice/typescript/eslint-sample$ npx eslint --init
You can also run this command directly using 'npm init @eslint/config'.
? How would you like to use ESLint? … 
  To check syntax only
  To check syntax and find problems
▸ To check syntax, find problems, and enforce code style
```

### 設問2 モジュールのインポート形式はなんですか？
import/exportを選択します。
``` 
? What type of modules does your project use? … 
▸ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these
```

### 設問3 使用しているフレームワークは何か？
とくに使用していないので、使用していないを選択します。 
```
✔ What type of modules does your project use? · esm
? Which framework does your project use? … 
  React
  Vue.js
▸ None of these
```

### 設問4 TypeScriptを使用してますか？
yesを選択します。
```
? Does your project use TypeScript? ‣ No / Yes
```

### 設問5 実行する環境はどこですか？
Node.js環境で実行するため、Nodeを選択します。
```
? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
✔ Node
```

### 設問6 ポピュラーなスタイルを使用しますか？
すでに定義されている代表的なスタイルが存在します。そのどれを選択するかが問われます。
今回はStandardを選択してみます。
```
? How would you like to define a style for your project? … 
▸ Use a popular style guide
  Answer questions about your style

? Which style guide do you want to follow? … 
▸ Standard: https://github.com/standard/eslint-config-standard-with-typescript
  XO: https://github.com/xojs/eslint-config-xo-typescript
```

### 設問7 configファイルはなんの形式がよいですか？
YAMLを選択。 
```
? What format do you want your config file to be in? … 
  JavaScript
▸ YAML
  JSON
```

### ファイルの作成完了
ここまで選択し、必要なパッケージのインストールをしてよいか聞かれるのでOKを押したら *.eslintrc.yml* が作成されます。
```.eslintrc.yml
env:
  node: true
  es2021: true
extends: standard-with-typescript
overrides: []
parserOptions:
  ecmaVersion: latest
  sourceType: module
rules: {}
```

### 設定ファイルの編集
上記で作成したファイルではtypescriptへのLinterとして使用するには足りない記述があるため、一部設定ファイルを編集する。
編集内容は以下。
```diff
env:
  node: true
  es2021: true
+ parser: '@typescript-eslint/parser' # 手順1でインストールしたパーサーを設定
extends: standard-with-typescript
+ plugins:
+     - '@typescript-eslint' # 手順1でインストールしたプラグインを指定
overrides: []
parserOptions:
  ecmaVersion: latest
+ project: ./tsconfig.json # プロジェクト内の型認識のため使用
  sourceType: module
rules: {}
```

設定ファイルの作成はここまでで完了です。

## 3. eslintの実行
では、定義ファイルの作成も完了しましたので早速tsファイルのサンプルを作成しeslintを実行してみます。
実行コマンドは以下になります。

**サンプルソース**
```sample.ts
hello : string = 'hello';
console.log(hello);
```

**実行コマンド**
```
eslint sanple.ts
```

**実行結果**
```
/home/asuhi/Documents/practice/typescript/eslint-sample/sample.ts
  1:5   error  'hello' is never reassigned. Use 'const' instead  prefer-const
  1:11  error  Unexpected space before the ':'                   @typescript-eslint/type-annotation-spacing
  1:29  error  Extra semicolon                                   @typescript-eslint/semi
  2:19  error  Extra semicolon                                   @typescript-eslint/semi

✖ 4 problems (4 errors, 0 warnings)
  4 errors and 0 warnings potentially fixable with the `--fix` option.
```

上から順にエラー内容をなぞると
1. helloはconstでいいよね
1. : の前にスペースあるよ
1. セミコロンは不要

という感じで無事eslintの実行まで実施できました。上記のメッセージに記載があるとおり、[--fix]のオプションをつけることで修正も自動でできるみたいですね。

ESLintの導入はここまで。次回は細かいルール設定も実施してみようと思います。