create-react-app + TypeScript の後の tslint/prettier 設定(VSCode)

普段 React + TypeScript でやってて、Lint(TSLint) と Prettier の設定を 
毎度やってるのですが忘れるのでまとめとくことにしました。[^1]

- [React](https://reactjs.org/)
- [TypeScript](https://www.typescriptlang.org/)
- [TSLint](https://palantir.github.io/tslint/)
- [Prettier](https://prettier.io/)
 
# 前提
以下、インストール済みであるとします。[^2]

- node
- yarn ※npm の場合、適宜読み替えて下さい
- create-react-app

# プロジェクト作成とパッケージインストール
以下のとおり。

```shell
# create-react-app(TypeScript)
> create-react-app --scripts-version=react-scripts-ts <your-project>
> cd <your-project>

# tslint, prettier
> yarn add --dev tslint prettier tslint-config-prettier tslint-config-airbnb tslint-plugin-prettier
```

- tslint のスタイルについては standard, google, airbnb などがありますが、私は airbnb がしっくりきています。[^3]
    - 参考: [Linting ES2015+ — ESLint with StyleGuides: Google, AirBnB, Common](https://medium.com/@uistephen/style-guides-for-linting-ecmascript-2015-eslint-common-google-airbnb-6c25fd3dff0)
    - airbnb 以外がよければ、```tslint-config-standard``` などとして好みのパッケージをインストールして下さい。その場合はこの後修正する設定ファイルでも airbnb の部分を当該のものに変更して下さい。

# 設定ファイル

修正ファイルは以下のとおり。

1. \<your-project\>/package.json
1. ~~\<your-project\>/tsconfig.json~~ ※ひとまず修正不要
1. \<your-project\>/tslint.json
1. \<your-project\>/.vscode/settings.json

### 1. package.json
create-react-app で生成されたデフォルト状態に、以下を追記。

```json:package.json
{
  ...,
  "scripts": {
    ...,
    "tslint:prettier-check": "tslint-config-prettier-check ./tslint.json",
    "tslint": "tslint --fix --force --format stylish --project ./tsconfig.json ./{src,__tests__}/**/*.{ts,tsx}",
    "prettier": "prettier --write ./{src,__tests__}/**/*.{ts,tsx}"
  },
  ...,
  "prettier": {
    "semi": true,
    "singleQuote": true,
    "printWidth": 120,
    "trailingComma": "es5"
  }
}
```
[GitHubGist: package.json](https://gist.github.com/katsu-o/fbae2c18b0c9e0b6efb4b92afd834c04#file-01-package-json)

- 以下 scripts の各コマンドについてです。コマンド内の ```./{src,__tests__}/**/*.{ts,tsx}``` のあたりは、対象とするファイルですので必要に応じて変更して下さい(私は基本的に \_\_tests\_\_ 以下にテストコードを書くのでこうしています)。
    - [tslint:prettier-check]: tslint と prettier の設定で衝突しているものをチェックする[^4]
    - [tslint]: tslint 実行して自動修正
    - [prettier]: prettier 実行して自動修正

### 2. tsconfig.json
ひとまず修正不要です。

### 3. tslint.json
create-react-app で生成されたものをまるっと書き換え。

```json:tslint.json
{
  "defaultSeverity": "error",
  "rulesDirectory": ["tslint-plugin-prettier"],
  "extends": ["tslint:latest", "tslint-react", "tslint-config-airbnb", "tslint-config-prettier"],
  "linterOptions": {
    "exclude": ["config/**/*.js", "node_modules/**/*.ts", "coverage/lcov-report/*.js"]
  },
  "rules": {
    "prettier": [
      true,
      {
        "semi": true,
        "singleQuote": true,
        "printWidth": 120,
        "trailingComma": "es5"
      }
    ],
    "no-console": false, // console のメソッドを許容しない
    "variable-name": [
      true, // 変数名をチェックする
      "ban-keywords", // 予約語の禁止
      "check-format", // lowerCamel と UPPER_SNAKE を許容
      "allow-pascal-case", // UpperCamel を許容
      "allow-leading-underscore" // 先頭の underscore を許容
    ],
    "import-name": false, // import 名の制約 #tslint-microsoft-contrib
    "ordered-imports": false, // import の順序指定
    "interface-name": false, // インターフェース名の制約(Iから始める)
    "no-empty-interface": false, // 空の Interface を許容しない
    "object-literal-sort-keys": false, // オブジェクトリテラルのキーをアルファベット順に並べることを強制する
    "object-literal-shorthand": false, // オブジェクトリテラルの省略記法を推奨する
    "jsx-no-lambda": false, // jsx 内での lambda の使用を許容しない
    "no-submodule-imports": [true, "excluded-module1", "excluded-module2"] // サブモジュールの import を許容しない
  },
  "jsRules": {}
}
```
[GitHubGist: tslint.json](https://gist.github.com/katsu-o/fbae2c18b0c9e0b6efb4b92afd834c04#file-02-tslint-json)

- ポイント
    - 　```"extends": ["tslint:latest", "tslint-react", "tslint-config-airbnb", "tslint-config-prettier"]``` の箇所で、どのスタイルをベースとするかを設定しています。この辺は自分のやりやすいように変更して下さい。 　
        - **<font color="Red">注意点</font>: "tslint-config-prettier" は一番最後に書くこと。**
         
    - 上記 rules の部分は**私の設定**です。この辺は自分のやりやすいように変更して下さい。
     
    - 参考: [TSLint core rules](https://palantir.github.io/tslint/rules/)


### 4. .vscode/settings.json
無ければディレクトリ(.vscode)ごと作成。

```json:.vscode/settings.json
{
  "editor.formatOnSave": true,
  "tslint.autoFixOnSave": true,
  "tslint.packageManager": "yarn",
  "prettier.singleQuote": true,
  "prettier.semi": true,
  "prettier.printWidth": 120,
  "prettier.trailingComma": "es5"
}
```
[GitHubGist: .vscode/settings.json](https://gist.github.com/katsu-o/fbae2c18b0c9e0b6efb4b92afd834c04#file-03-vscode-settings-json)

### 備考: Prettier の整合性(VSCode による自動修正とコマンド実行)
上記各設定ファイルにおける prettier の設定を合わせて下さい。
VSCode のファイル保存で自動修正されたものと、コマンドから修正したもので整合性が取れなくなります。

# 最後に
チーム開発時にはもちろんですが、個人でもコーディングスタイル／フォーマットは非常に重要です。可読性の低さはバグと直結します。
Lint(TSLint) は以前から導入していたこともあり、改めての感動はさほど無いのですが(無論感謝してます)、Prettier スゴイです。思えば昔は人力でやってました。
私はもうこれ無しでコーディングする気にはならないです。

ちなみに Prettier を導入するにあたり、下記サイトが非常に参考になりました。
[ESLint(あるいはTSLint)とPrettierを併用する](https://tech-1natsu.hatenablog.com/entry/2018/01/07/154941)
git commit 時に hook を掛けて Prettier を掛ける方法なども書いてあります。


それでは。 


[^1]: 開発は VSCode(Windows 10) でやってます。その際の備忘録です。
[^2]: 現時点(2018/9)での私の環境は [node: 10.7.0 (npm: 6.1.0)][yarn: 1.9.4][cra: 1.5.2] です。
[^3]: それぞれ試してみましたが、「セミコロン必須」「JSDocs 必須は困る」という感じで airbnb になりました。
[^4]: [TypeScriptプロジェクトにコードフォーマッタPrettierを導入する](https://qiita.com/akisx/items/4b90106c7faca4965852) <- 分かりやすいです。