TSLintを使うTypeScriptプロジェクトにコードフォーマッタPrettierを導入する

TypeScriptのプロジェクトへのPrettierの導入紹介です。

(2019-02-11 ESLintのTypeScriptサポート強化が表明されていることをふまえて追記: この投稿はTSLintとPrettierを組み合わせる場合について記述しています。ESLint+Prettier for TypeScriptについてではないことにご注意ください。)

## Prettierとは

https://github.com/prettier/prettier

Prettierはコードフォーマッタです。JavaScript(ES2017含む)、JSX、Vue、Flow、TypeScript、CSS(Less,SCSS)、JSON、GraphQL、Markdownとフロントエンド開発で使われる言語/仕様に多く対応しています。適用することでコードに一貫したスタイルをもたらします。

一貫したスタイルは読みやすさ、ひいては保守性につながる大正義です。

また、後述するように保存時に実行するように設定すれば、整形を自動化できるので見た目の調整に煩わされることなくコードが書けます。途中見た目を多少雑に書いても平気なので本当に快適です。一度導入するとなしには戻れないです。

GitHubスターはリリースから一年ちょっとで2万近く(2018/01現在)、React本体やBabel、Redux、Material-UI等のメジャーどころでも採用されていることから、廃れる心配もほぼないでしょう。[^1]

デメリットなんてPrettierのスタイルが気に入らない場合がある、くらいのもので現状導入しない理由はないと思います。


### Linterじゃだめなの？

同じようにコードを静的解析するツールとしてLinterがあります。Linterを導入しているところは多いと思いますが、Linterがカバーできないものもあります。例えばコードの行の最大長です。`max-len`で検出は可能ですが整形までは行えません。

例を出すとTSでReduxを書いていると、次のようなコードが出てきます。1行が長くなりがちで、またどこで改行するかは人によってブレやすいやつです。

```ts
type FooAction = Foo1Action | Foo2Action | Foo3Action | Foo4Action | Foo5Action | Foo6Action | Action;
```

これをスパッと下のように整形し、スタイルを統一してくれます。

```ts
type FooAction =
  | Foo1Action
  | Foo2Action
  | Foo3Action
  | Foo4Action
  | Foo5Action
  | Foo6Action
  | Action;
```

一方でPrettierの守備範囲はあくまでフォーマットとそのスタイルルール(最大長`max-len`や空白`keyword-spacing`といったもの)です。未使用変数の宣言(`no-unused-vars`)などのバグの温床の検出はLinterに任せましょう。

## 導入

Prettierをインストールします。

```sh
yarn add prettier --dev --exact
# or
npm install --save-dev --save-exact prettier
```

## Option設定

Prettierは"Opinionated Code Formatter"を謳っているのであまりあれこれ設定するものではないと思いますが、個人やチームの方針もあるので必要があればOption設定しましょう。

Prettierの設定方法は以下の3通り。

- `.prettierrc`ファイルを用意しYAMLまたはJSONで記述する
- `prettier.config.js`ファイルを用意し設定オブジェクトをexportする
- `package.json`に`"prettier"`キーを用意し記述する

`.prettierrc`であれば、こんな感じで書いてプロジェクトのルートディレクトリに置いてあげればOK。設定できる項目についてはhttps://prettier.io/docs/en/options.html を。

```json:.prettierrc
{
  "singleQuote": true
}
```

## TSLintと統合

そのままではTSLintの設定と競合してフォーマットをかけた側からTSLintに怒られることになるので同居できるようにします。方針は、「スタイルに関するものはPrettierに任せ、それ以外をTSLintに任せる」です。

`tslint-config-prettier`と`tslint-plugin-prettier`を利用します。

### tslint-config-prettier

https://github.com/alexjoverm/tslint-config-prettier

`tslint-config-prettier`はTSLintの設定のうちPrettierと衝突するものを無効化してくれるパッケージ。

```sh
yarn add prettier --dev tslint-config-prettier
# or
npm install --save-dev tslint-config-prettier
```

インストールしたら`tslint.json`の`extends`のケツに以下のように追加します。

```json:tslint.json
{
  "extends": [
    "tslint-react", 
    "tslint-config-prettier"
  ]
}
```

これでフォーマットに関係するルールが無効化されます。

#### 衝突している設定を調べる

`tslint-config-prettier`はPrettierとTSLintで衝突している設定があるかチェックするツールも提供しています。`package.json`に以下のように追加し、`yarn tslint-check`を実行すればOK。

```json:package.json
{
  "scripts": {
    "tslint-check": "tslint-config-prettier-check ./tslint.json"
  }
}
``` 

### tslint-plugin-prettier

競合を解決する`tslint-config-prettier`に対し、`tslint-plugin-prettier`はTSLintのチェックをかけるときに一緒にPrettierのチェックもかけてリポートしてくれるプラグイン。

```sh
yarn add --dev tslint-plugin-prettier
# or
npm install --save-dev tslint-plugin-prettier
```

インストールしたら`tslint.json`に以下のように追記します。

```json:tslint.json
{
  "rulesDirectory": ["tslint-plugin-prettier"],
  "rules": {
    "prettier": true
  }
}
```

これでPrettierのスタイルに沿ってなければ他のTSLintルールと同様に警告がでるようになります。

## VSCode連携

僕のメインエディタがVSCodeなので。VimやEmacs、Atomなどメジャーなエディタであればプラグインがあるのでそれら利用の人は別途調べてください。

まずはPrettierプラグイン https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode をインストールします。

これで対象ファイルを開いた状態で`⌥+⇧+F(windows: alt+shift+F)`でフォーマットを走らせることができます。ただ毎回ショートカットうつのも面倒なので、保存時に自動的に走るようにするといい感じです。

ユーザー設定`settings.json`に下の設定を入れてあげます。これで保存時に自動的にフォーマットされます。

```json:settings.json
{
  "editor.formatOnSave": true
}
```

どのファイルでも走るのが嫌であれば特定のファイルだけ対応させることもできます。

```json:settings.json
{
  //*.ts
  "[typescript]": {
    "editor.formatOnSave": true
  },
  //*.tsx
  "[typescriptreact]": {
    "editor.formatOnSave": true
  }
}
```

僕の今のチームでは保存時フォーマットの設定をルール付けして運用していますが、十分だと感じています。

公式では他に`git commit`をフックしてコミット時にフォーマットする方法 (https://prettier.io/docs/en/precommit.html) が紹介されています。プロジェクトの体制に応じて運用方法を決めればよいでしょう。

## 最後に

コードスタイルには個人差がでますが、それらをチームで擦り合せルール運用しても労力に見合いません。だったらいっそPrettierのスタイルに寄せて自動化してしまいましょう。

細々したスタイルをレビューで指摘し手作業で整形するのは終わりにしましょう！



[^1]: むしろv1.10でPlugin機能が導入されPython/PHP/Swiftのプラグインが開発中など、さらに発展しそう。