React+TypeScript環境にESLint+Prettierを導入する


みなさま初めまして。
ニジボックスに入社し、フロントエンドエンジニアを名乗り始めてから約1年が経ちました。

4ヶ月前くらいまで、Lintって何！？って感じであんまり良さを感じていなかった（というか何者か分かっていなかった）（というか既に案件のリポジトリには導入されていたので何も考えずに使っていた）ので、せっかくの機会なので調査してみました。
React+TypeScript環境にESLint+Prettierを導入するまでの手順にして備忘としてまとめてみます。

## create-react-app

create-react-appを使えばコマンド一つでReactを書き始めることができます。
`--template typescript`オプションを付けなければJSでも書けます。
`ts-app`の部分はお好きなプロジェクト名に変更してください。

```
npx create-react-app ts-app --template typescript
```

## Prettier
Prettierはコードを自動整形するツールです。
ESLintにもコードフォーマットの機能はあるんですが、Prettierの方がコードフォーマットとしては優秀なようなので、ESLintとPrettierを併用するのが主流のようです。
なにはともあれ、Prettierをインストールしましょう。

```
npm install --save-dev prettier
```

### Prettierの設定ファイルを作成

```Javascript:.prettierrc.yml
---
printWidth: 80
tabWidth: 2
singleQuote: true
trailingComma: none
jsxBracketSameLine: true
semi: false
arrowParens: avoid
```

- `printWidth` 折り返しをする行の長さを指定（公式曰くおすすめは80文字なので従います）
- `semi` 行の最後にセミコロンをつけるかどうか指定
- `arrowParens` 引数が１つの時にはカッコを省略するかどうか

などなど、<a href="https://prettier.io/docs/en/options.html">公式</a>に指定できるオプションは詳しく載っています。この辺りはお好みでどうぞ。

### いったん動作確認
`package.json`に以下のscriptを追加してきちんと動作するか確認してみます。

```json:package.json
{
  "scripts": {
    "fix:prettier": "prettier --write src",
    "lint:prettier": "prettier --check src"
  }
}
```

## ESLint
これってなんて読んでますか？
ミスチル的には「エス」なんですが、やっぱり「イーエス」が正しいんでしょうか。

ちなみにESLintは、JavaScriptのための静的検証ツールで、コードを実行する前に明らかなバグを見つけたり、括弧やスペースの使い方などのスタイルを統一するために使用されます。
先述の通り、ESLintでもコードを自動的に修正することはできますが、自動整形という点においてはPrettierの方が優れているため、コードの構文チェックはESLintが行い、コードの整形はPrettierに任せたいと思います。

ただし、この自動整形は、括弧が足りなかったり、カンマが足りなかったりした場合に自動で追加してくれるなんてことはないので、そこは自分で整えてあげる必要があります。

では以下のコマンドを実行して、ESLintを導入します。

```
npx eslint --init
```

```
ESLintをどのように使用しますか
? 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
```

```
あなたのプロジェクトはどんな種類のモジュールを使っていますか
❯ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these
```

```
プロジェクトで使用しているフレームワークはどれですか
? Which framework does your project use? … 
❯ React
  Vue.js
  None of these
```

```
プロジェクトはTypeScriptを使用していますか
? Does your project use TypeScript? › Yes
```

```
コードはどこで実行されますか
? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
  Node
```

```
プロジェクトのスタイルをどのように定義しますか
? How would you like to define a style for your project? … 
❯ Use a popular style guide
  Answer questions about your style
  Inspect your JavaScript file(s)
```

```
どのスタイルガイドに従いたいですか
? Which style guide do you want to follow? … 
❯ Airbnb: https://github.com/airbnb/javascript
  Standard: https://github.com/standard/standard
  Google: https://github.com/google/eslint-config-google
```

```
設定ファイルをどの形式にしますか
? What format do you want your config file to be in? … 
❯ JavaScript
  YAML
  JSON
```

```
関連する必要なパッケージをnpmでインストールするか
? Would you like to install them now with npm? › Yes
```


パッケージを全てインストールし終わったら、
追加で、Prettierとの連携用のパッケージを導入します。

```
npm install --save-dev eslint-config-prettier eslint-plugin-prettier
```

- `eslint-config-prettier`
Prettierと競合する可能性のあるESLintのルールをすべてオフにする

- `eslint-plugin-prettier`
ESLint上でPrettierを動作させるために使用する


### ESLintの設定ファイルを編集する
インストールが終わったら、ルートディレクトリに`.eslintrc.js`ファイルが作成されているのでこちらを編集していきます。

```js:.eslintrc.js
module.exports = {
  // ソースコードが対象としている環境
  // ここの指定によって使えるクラスや関数の種類が変わる
  env: {
    browser: true,
    es2021: true
  },
  // 設定をまとめて変更する場合はextendsに記述する
  // 配列の0番目から順番に上書きされるため、Prettier関連の記述は最後に追加する
  extends: [
    'airbnb',
    'airbnb/hooks',
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier',
    'prettier/@typescript-eslint'
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 12,
    sourceType: 'module'
  },
  // 機能を追加するプラグインを記述する
  plugins: ['react', '@typescript-eslint', 'prettier'],
  // プロジェクト内部で個別に機能を切り替えたい時はrulesに記述する
  rules: {
    'no-use-before-define': 'off',
    '@typescript-eslint/no-use-before-define': ['error'],
    'react/jsx-filename-extension': 'off',
    'react/jsx-closing-bracket-location': [
      'error',
      { selfClosing: 'tag-aligned', nonEmpty: 'after-props' }
    ],
    'react/jsx-one-expression-per-line': 0,
    'import/no-unresolved': ['off', { caseSensitive: true }],
    'import/extensions': 'off'
  },
  settings: {
    react: {
      version: 'detect'
    }
  }
}

```
- **`extends`**は、ESLintのルールのON/OFFを設定するもので、例えば`'eslint:recommended'`は、<a href="https://eslint.org/docs/rules/">推奨設定</a>（チェックマークがついているもの）を全てONにする役割を持っています。それが、配列の0番目から上書きされていきます。


- **`plugins`**は、ルールそのものを追加できます。
上に入っていないものでも、例えば
    - `eslint-plugin-immutable` JavaScriptのすべてのミューテーションを無効にするESLintプラグインです。今回は入れていませんが、Reactで書くなら入れた方が良さそうな気がする
    - `eslint-plugin-import` import/export構文をサポートし、ファイルパスとインポート名のスペルミスの問題を防ぐことができるのでぜひ入れたい


### いったん動作確認（パート２）

ESLint単体でもきちんと動作するか確認しておきましょう。

```json:package.json
{
  "scripts": {
    "fix": "run-s fix:prettier fix:eslint",
    "fix:eslint": "eslint src --ext .ts,tsx --fix",
    "lint": "run-p lint:prettier lint:eslint",
    "lint:eslint": "eslint src --ext .ts,tsx",
  }
}
```

## VSCode
VSCodeで使用する場合、保存時に自動整形されるように設定ファイルを作成します。
以下のように記述することで、ESLintのルールで自動整形されるようになります。

```json:.vscode/extensions.json
{
  "recommendations": [
    "streetsidesoftware.code-spell-checker"
  ],
  "unwantedRecommendations": []
}
```

```json:.vscode/settings.json
{
  "eslint.lintTask.enable": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}
```

また、`tsconfig.json`で下記のようなエラーが出ている場合があります。
`Cannot use JSX unless the '--jsx' flag is provided`

```json:tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx"
           ~~~~~~~~~~~
  },
}
```
VSCodeで古いバージョンのTypeScriptを使用している可能性があるので、以下の手順でバージョンを変更します。

- コマンドパレットに移動（Control + Shift + P）
- 「TypeScript：TypeScriptバージョンを選択...」を選択
- 「ワークスペースバージョンを使用」を選択（4.1.3）


`tsconfig.json`は、TypeScriptで記述されたコードをJavaScriptにコンパイルする際のルールが記述されたファイルです。
詳しくは<a href="https://www.typescriptlang.org/tsconfig">公式</a>へどうぞ。


## おまけ
### ESLintの警告を特定のコードだけ除外したい場合
変数名の規則はcamelCaseだが、サーバーのレスポンスのみsnake_caseを許容したい場合など、特定の行やブロック内のみ警告を除外したい場合には、下記のようにコメントを入れることで無効化できます。

```
// eslint-disable-next-line camelcase
const { status_code } = await res.json();
```
```
/* eslint-disable camelcase */

const { status_code } = await res.json();

/* eslint-enable camelcase */
```


以上、ここまで来れば、あなたがエディター上でどんなに汚いコードを書いたとしても、Lintが綺麗に整頓してくれるようになっているでしょう👏
みなさま良いクリスマスを〜