目的

Angular の Linter を ESLint & Prettier にする。

  • node 14.8
  • Angular 11

Angular プロジェクトの作成

$ npx -p @angular/cli ng new angular-eslint-proj

# プロジェクト作成時のオプションはやりたい事の文脈と関連しないので適当に選択しておく

? Do you want to enforce stricter type checking and stricter bundle budgets in the workspace?
  This setting helps improve maintainability and catch bugs ahead of time.
  For more information, see https://angular.io/strict Yes
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS

$ cd angular-eslint-proj

TSLint > ESLint へのマイグレーション

参考ドキュメント
angular-eslint: Migrating an Angular CLI project from Codelyzer and TSLint

Angular プロジェクトに ESLint を組み込む。

$ ng add @angular-eslint/schematics

Installing packages for tooling via npm.
Installed packages for tooling via npm.
UPDATE package.json (1704 bytes)
✔ Packages installed successfully.

Linter を TSLint から ESLint に変更する。

$ ng g @angular-eslint/schematics:convert-tslint-to-eslint angular-eslint-proj

CREATE .eslintrc.json (1084 bytes)
UPDATE angular.json (3606 bytes)

.eslintrc.json が生成され angular.json に変更が加えられる。

// .eslintrc.json
{
  "root": true,
  "ignorePatterns": [
    "projects/**/*"
  ],
  "overrides": [
    {
      "files": [
        "*.ts"
      ],
      "parserOptions": {
        "project": [
          "tsconfig.json",
          "e2e/tsconfig.json"
        ],
        "createDefaultProgram": true
      },
      "extends": [
        "plugin:@angular-eslint/ng-cli-compat",
        "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
        "plugin:@angular-eslint/template/process-inline-templates",
      ]
    }
  ]
  ...
}
// angular.json
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "angular-eslint-proj": {
      "architect": {
        "lint": {
          "builder": "@angular-eslint/builder:lint",
          "options": {
            "lintFilePatterns": [
              "src/**/*.ts",
              "src/**/*.html"
            ]
          }
        }
      }
    }
  }
  ...
}

TSLint の削除

$ rm ./tslint.json

# Codelyzer(TSLint のルールセット)も使わないので削除
$ npm uninstall codelyzer

Prettier 導入

参考ドキュメント
Prettier: Basic Configuration

Prettier の設定ファイルを作成する。

$ touch .prettierrc.js
// .prettierrc.js
module.exports = {};

Prettier の設定を ESLint のルールとして取り込む。 これによって Prettier が整形したコードが Lint のエラーとして検出される事を防ぐ。

$ npm install -D eslint-config-prettier
$ npm install -D prettier
// .eslintrc.json
"extends": [
  "plugin:@angular-eslint/ng-cli-compat",
  "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
  "plugin:@angular-eslint/template/process-inline-templates",
  
  // この 2 行を追加
  "prettier",
  "prettier/@typescript-eslint"
],

ESLint と Prettier の設定にコンフリクトがないかチェックする。 コンフリクトする場合は @angular-eslint/xxx を無効にする。

参考ドキュメント
eslint-config-prettier: CLI helper tool

./node_modules/.bin/eslint-config-prettier ./src/app/app.component.ts

# コンフリクトなし
No rules that are unnecessary or conflict with Prettier were found.

Prettier のルールを追加

// .prettierrc.js
module.exports = {
  // string のリテラルにシングルクォートを強制
  singleQuote: false
};

利用できるルールは公式ドキュメントに記載されている。

@typescript-eslint のルールを追加

error/warn/off のいずれかを指定する。

"overrides": {
  "rules": {
    // 空のインターフェースを許容しない
    "@typescript-eslint/no-empty-interface": "error"
  }
}

利用できるルールは公式ドキュメントに記載されている。

WIP: ESLint のルールを追加

利用できるルールは公式ドキュメントに記載されている。

ESLint: Rules

Lint の実行

ng lint でエラーを検出する。ng lint --fix でエラーが検出されたコードを修正する。

> ng lint

/angular-eslint-proj/src/app/app.component.ts

error  An empty interface is equivalent to `{}`  @typescript-eslint/no-empty-interface

✖ 1 problem (1 error, 0 warnings)
Lint errors found in the listed files.

ESLint の推奨ルールを取り込む

// .eslintrc.json
{
  ...
  "overrides": [
    {
      "files": [],
      "parserOptions": {},
      "extends": [
        // この行を追加
        "eslint:recommended",
        
        "plugin:@angular-eslint/ng-cli-compat",
        "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
        "plugin:@angular-eslint/template/process-inline-templates",
      ]
    }
  ]
  ...
}

Lint を実行するとエラーが大量に検出される。

$ ng lint

Linting "angular-eslint-proj"...

/Users/matsuoka/work/ringtail003/angular-eslint-proj/src/app/app.component.spec.ts
   5:1  error  'describe' is not defined    no-undef
   6:3  error  'beforeEach' is not defined  no-undef
  17:3  error  'it' is not defined          no-undef
  ...

✖ 8 problems (8 errors, 0 warnings)

/Users/matsuoka/work/ringtail003/angular-eslint-proj/src/app/app.component.ts
  12:11  error  'x' is assigned a value but never used  no-unused-vars

✖ 1 problem (1 error, 0 warnings)

/Users/matsuoka/work/ringtail003/angular-eslint-proj/src/test.ts
  11:11  error  'path' is defined but never used    no-unused-vars
  11:25  error  'deep' is defined but never used    no-unused-vars
  ...

不必要なルールは ESLint のルールから除外する。

{
  "overrides": [
    {
      "rules": {
        "@angular-eslint/component-selector": [],
        "@angular-eslint/directive-selector": [],
        
        // 除外する
        "no-undef": "off",
        "no-unused-vars": "off"
      }
    }
  ]
  ...
}

VSCode の設定

VSCode のエラー表示(赤い破線)を ESLint と連動させる。

デフォルトのフォーマッターを Prettier に設定し、ファイル保存時にフォーマットを実行する。

"[typescript]": {
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.codeActionsOnSave": {
  "source.fixAll.eslint": true
}