[初心者向け]TypeScript用にESLintとPrettierを導入する

# 概要
## 対象

- TypeScriptにこれからESLint, Prettierを導入するビギナー向け
- ESLintの設定にあまり詳しくない方
- npmパッケージのインストールの仕方がわかる
- 筆者が初心者です。

そのため、手順を飛ばさずに書いたため、よくご存知の方にとっては**無駄な記述が多く**あります。そういう方は他の簡潔に書かれた記事をご参照ください。

ESLintとPrettierについてよくご存知でない方は以下の記事がよくまとまっていて参考になりましたので、ご参照ください。

- [Prettier 入門 ～ESLintとの違いを理解して併用する～ \- Qiita](https://qiita.com/soarflat/items/06377f3b96964964a65d)
- [Prettierの導入方法 \- フロントエンド開発で必須のコード整形ツール \- ICS MEDIA](https://ics.media/entry/17030/)



## 目的

この記事はTypeScriptの初心者の方がESLintとPrettierを導入するための手順と**最低限必要な設定項目**について説明したものです。導入しようとした際に、記事によって、書いていることが異なっていて、混乱したので、ドキュメントを参照しながら、メモした内容をまとめました。

また、手動で設定ファイルを書くやり方と自動生成するやり方の両方を併記しています。**必要に応じて、飛ばして下さい**。

ちなみに、TypeScriptのlinterではTSLintがありますが、2019年中に非推奨になる予定です。

- [脱TSLintして、ESLint TypeScript Plugin に移行する \- Qiita](https://qiita.com/suzuki_sh/items/fe9b60c4f9e1dbc5d903)



## 動作環境

- macOS Mojave
- Node.js 10.16.0
- npm 6.11.3

## 最短ルート: コピペだけする場合
コピペ用コマンドと最小限の設定ファイルのは[こちら](#設定のまとめコピペ用)へまとめてあります。

##更新
- airbnbのスタイルガイドをTypeScriptに対応させるためにルールの追記。


# TypeScriptのためのESLint設定

## 方法1: 設定ファイルを自動生成する

手動で設定ファイルを書きたい人は[次の項目](#方法2手動で設定する場合)まで飛ばして下さい。ここでは以下のような方のための説明です。

- 　設定ファイルを書くのにくたびれた人

eslint --init を使うと、項目を選択するだけで設定ファイルを作成したり、必要なパッケージを自動でインストールできます。グローバルにESLintをインストールすると、直接`eslint`と打てますが、グローバルになるべくインストールしたくないので、`npx`コマンドを使います。npxについては以下の記事を参照して下さい。



- [npm 5\.2\.0の新機能！ 「npx」でローカルパッケージを手軽に実行しよう \- Qiita](https://qiita.com/tonkotsuboy_com/items/8227f5993769c3df533d)


**1. 初期設定の開始**

```bash
npx eslint --init
```


最初の質問が表示されます。上下キーで選択肢を選び、エンターキーで確定します。

ESLintのルールを自分で設定するのは大変なので、スタイルガイドを採用したいので、1番下を選びます。スタイルガイドがいらない場合は真ん中を選びます。

```
? 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. モジュールシステムの選択**

```

? What type of modules does your project use? (Use arrow keys)
❯ JavaScript modules (import/export) 
  CommonJS (require/exports) 
  None of these 
```

モジュールのスタイルを指定。1番上を選択します。

**3. React, Vue.jsを使うかどうか**

```
? Which framework does your project use? 
  React 
  Vue.js 
❯ None of these 
```
最低限の設定をするため、ライブラリーは使わないので、ここでは一番下を選びます。

**4. TypeScriptを使うかどうか**

```
? Does your project use TypeScript? (y/N) 
```

yを入力して、エンターキーで確定

**5. 動作環境**

```
? Where does your code run? (Press <space> to select, <a> to toggle all, <i> 
to invert selection)
 ◉ Browser
❯◉ Node
```

スペースキーで選択、選択の解除ができます。必要に応じてNodeも選択します。

**6. スタイルガイドを使うかどうか**

```
? How would you like to define a style for your project? (Use arrow keys)
❯ Use a popular style guide 
  Answer questions about your style 
  Inspect your JavaScript file(s) 
```

スタイルガイドを使いたいので、一番上を選びます。最初に`To check syntax and find problems `を選んだ場合は表示されません。

**7. スタイルガイドを選択**

```
? 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) 
```

お好みで選びます。とりあえず、ここではAirbnbを選択します。

**8. 設定ファイルの形式を選択**

```bash

? What format do you want your config file to be in? 
  JavaScript 
  YAML 
❯ JSON 
```

どれでもいいとは思いますが、VS Codeを使っている場合、JSONだとESLint向けの自動補完機能が機能します。後々、ルールをカスタマイズするときに便利なので、JSONを使います。


**9. パッケージをインストールするかどうか**

```
? Would you like to install them now with npm? (Y/n) 
```

必要なnpm パッケージを入れるので、`Y`と入力し、エンターキー

`n`の場合は、設定ファイル(eslintrc.jsonなど)だけ生成されます。すでにパッケージはインストール済みの時に使います。

次はPrettierの設定を行います。次の[Prettierの設定](#TypeScriptのためのESLintとPrettierの併用設定)まで飛ばして下さい。

## 方法2: 手動で設定する場合

**1. パッケージのインストール**

```bash
npm i -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser

# eslintがもう入っている方
npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser

#省略形で書いていますが、以下と同義です。
# iがinstall
# -D が--save-devの省略形です。以降、この記事では省略形で書きます。
npm install <Package Name> --save-dev
```
**パッケージ内容**

- [ESLint](https://github.com/eslint/eslint): ESLint本体

- [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint): TypeScriptとESLintは異なるASTを用いているので、その間をうまく調整する必要があるらしいです。筆者はよくわかっていません。ESLintがTypeScriptを理解できるようにするために入れます。デフォルトのparserはespreeです。

- [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint): interfaceなどTypeScript独自の機能のためのlint rulesを動かすために必要です。


---
AST関連記事

- [-社内勉強会TechLunchで"JavaScript ASTことはじめ"という発表をしました \- Medley Developer Blog](https://developer.medley.jp/entry/2018/06/22/130000)

公式ドキュメント

- [typescript\-ESLint/typescript\-ESLint: Monorepo for all the tooling which enables ESLint to support TypeScript](https://github.com/typescript-ESLint/typescript-ESLint#how-do-i-configure-my-project-to-use-typescript-ESLint)


**2. 設定ファイルの作成**

VS Codeだと、JSON形式で作成すると、自動補完が効きます。のちにルールをカスタマイズするときに楽ですので、JSONで作成します。JavaScript形式でも作成できます。設定ファイルの書き方はここでは2パターン紹介します。

```bash
touch .eslintrc.json
```


**2.2.その1: 自分でTypeScript用のルールを定義したい場合**

```(全体)eslintrc.json
{
  "parser": "@typescript-eslint/parser",
   "parserOptions": { "sourceType": "module" },
  "plugins": ["@typescript-eslint"],
}
```
TypeScript用のルールを勝手にオンにされたくなく、必要に応じて、自分でルールを追記する場合。


**2.2. その2: TypeScript向けの推奨ルールを適応させたい場合**

```(全体)eslintrc.json
{
  "extends": ["plugin:@typescript-eslint/recommended"]
}
```
TypeScript向けの推奨ルールをオンにする場合はこのように書きます。
**1行だけ**でその1で書いたparser, parserOptions, pluginsが設定され、さらに推奨ルールが適応されます。しばしば両方書いているケースがありましたが、どちらか一方で十分です。以降は**その2を採用している記述で統一**します。

**2.3.共通の追記**

必要に応じて、以下をextendsの下に追記します。

```(抜粋)eslintrc.json
"env": {
        "browser": true,
        "es6": true,
        "node": true
}
```

**3. スタイルガイドを導入**
**3.1. スタイルガイドのパッケージのインストール**
[Airbnbのスタイルガイド](https://www.npmjs.com/package/eslint-config-airbnb-base)を導入する場合は以下のコマンドを入力します。

```bash
npx install-peerdeps --dev eslint-config-airbnb-base
```
**3.2. スタイルガイドを反映させる**
`eslintrc.json`に追記します。書く際は順番に注意して下さい。スタイルガイドの方が先です。通常のJavaScript向けのスタイルガイドを後ろからTypeScript用の設定で上書きするイメージです。


```(全体)eslintrc.json
{
  "extends": [
    "airbnb-base",//ここに追記
    "plugin:@typescript-eslint/recommended" 
  ],
  "env": {
        "browser": true,
        "es6": true,
        "node": true
  }
}

```
# TypeScriptのためのESLintとPrettierの併用設定

**1. パッケージのインストール**

ESLintとPrettierが競合しないように以下のパッケージを入れます。

```bash

npm i -D  prettier eslint-config-prettier eslint-plugin-prettier
```

- [prettier](https://github.com/prettier/prettier): 本体
- [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier): 競合するルールをオフにします。

- [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier): ESLlintでPrettierのチェックを行うために入れます。



設定ファイルには以下のように書きます。

```(抜粋)eslintrc.json
{
  "extends": [
    "airbnb-base",
    "plugin:@typescript-eslint/recommended", 
    "plugin:prettier/recommended", //追記
    "prettier/@typescript-eslint" //追記
  ],

```

`"plugin:prettier/recommended"`と`"prettier/@typescript-eslint"`を追記します。**記述する順番に気をつけて下さい**。ESLintのルールを上書きするために、最後の方に書きます。スタイルガイド=>TypeScriptのESLintの設定=>Prettierの順番で書きます。
記述について説明すると、extendsの`"plugin:prettier/recommended"`は自動で以下の設定をしています。

```json
{
  "extends": ["prettier"],
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error" //ESLintでPrettierの規則もエラーとして検出する設定
  }
}
```

一部の記事では両方とも書いているケースがありますが、どちらか一方で十分です。

また、`prettier/@typescript-eslint`は`@typescript-eslint/eslint-plugin`をサポートするために必要な記述です。

------

公式ドキュメント

[Integrating with Linters · Prettier](https://prettier.io/docs/en/integrating-with-linters.html)

[prettier/ESLint\-plugin\-prettier: ESLint plugin for Prettier formatting](https://github.com/prettier/ESLint-plugin-prettier)

**2. .prettierrcの作成**

フォーマットのルールを指定できますが、とりあえず以下の記述だけ加えておきます。シングルクォテーションの使用を強制します。

```json
{
  "singleQuote": true
}
```
これで終わりです。

# 設定のまとめ(コピペ用)


```bash
# 設定ファイルを作成
touch .eslintrc.json .prettierrc

# パッケージのインストール
npm i -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser prettier eslint-config-prettier
 eslint-plugin-prettier

# Airbnbのスタイルガイドをインストール
npx install-peerdeps --dev eslint-config-airbnb-base
```

```.eslintrc.json
{
  "extends": [
    "airbnb-base",//スタイルガイドがいらない場合や他を使う場合はここを書き換える
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "env": {
        "browser": true,
        "es6": true,
        "node": true
  },
  "parserOptions": {
    "sourceType": "module"
  }
}
```

.prettierrcに書く。

```json
{
  "singleQuote": true
}

```


# 補足: エラー Unable to resolve path to module の解決策
![moduleのエラー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113102/144567a6-ef66-354e-ac7f-44f07fa520f1.png)

importする際にエラーが出ます。これはairbnbのスタイルガイドが原因で、TypeScriptに対応していないために起こります。原因となっているルールは以下の2箇所です。

```imports.js
  settings: {
    'import/resolver': {
      node: {
        extensions: ['.mjs', '.js', '.json']
      }
    },

//中略

   rules: {
      'import/extensions': ['error', 'ignorePackages', {
          js: 'never',
          mjs: 'never',
          jsx: 'never',
    }],
   }
```

ソースコード: [javascript/imports\.js at master · airbnb/javascript](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/imports.js)


以下の2点を`.eslintrc.json`に追記します。ここでは一応`tsx`にも対応させていますが、必要に応じて。

```(抜粋)eslintrc.json
 "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"]
      }
    }
  }
```



```(抜粋)eslintrc.json
   "rules": {
       "import/extensions": [{
            "js":"never",
            "jsx":"never",
            "ts":"never",
            "tsx":"never"
           }]
   }
```

------

解決にあたり、参考にしたページ
- [node\.js \- Typescript eslint \- Missing file extension "ts" import/extensions \- Stack Overflow](https://stackoverflow.com/questions/59265981/typescript-eslint-missing-file-extension-ts-import-extensions)