2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ESLintのenv、extends、overrides、parser、parserOptions、plugins、rulesをざっくり理解する

Last updated at Posted at 2023-06-02

背景

ある開発者の環境ではLintエラーが発生するけど、自分の環境では発生しないという現象がきっかけでした。(原因は本記事とは関係のないところにあったのですが、、)

ESLint自体を見直す機会になったので、仕事がない分、勉強したんだぞという証拠を残しておきます。

環境

  • OS

Windows WSL2 Ubuntu 20.04

  • Node
$node -v
V18.12.1

$npm -v
8.19.2
  • ESLint

.eslintrc.jsonで設定を記述します。
V9.0.0で廃止されるスタイルのようです。知りませんでした。まぁでもコンセプトは変わらないので大丈夫:innocent:

$npx eslint --version 
V8.41.0

セットアップ

ゼロから作ってみると達成感が増すので、ドキュメントに沿って、設定してみます。

# 適当な作業フォルダを作成
$cd ~/work
$mkdir eslint-practice
$cd eslint-practice

# node プロジェクトを生成
$npm init -y

# eslint の初期化処理と選択肢は以下を選んでいます。
$npm init @eslint/config
# 1. To check syntax and find problems
# 2. JavaScript modules
# 3. React
# 4. Yes(TypeScript)
# 5. Browser
# 6. JSON
# 7. Yes(Install packages)
# 8. npm

# package.jsonの中身を確認してみると、TypeScriptとReactに関連するeslintパッケージもInstallされていることが分かります。
$cat package.json
{
  "name": "eslint-practice",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.59.8",
    "@typescript-eslint/parser": "^5.59.8",
    "eslint": "^8.41.0",
    "eslint-plugin-react": "^7.32.2"
  }
}

# TypeScriptがnode_modulesに入るのですが、parserとの互換性エラーがでるので、明示的にVersionを指定してInstallします。
$ npm install -D typescript@5.0.4

# eslintも動作することが確認できます。
$npx eslint --version
v8.41.0

# 設定ファイルも生成されています
$ ls -a
.eslintrc.json  node_modules  package-lock.json  package.json

設定を確認

ここからが本題です。デフォルトで生成された生成ファイルを解剖していきましょう。

$ cat .eslintrc.json
{
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    "overrides": [
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "@typescript-eslint"
    ],
    "rules": {
    }
}

ESLintがコードチェックする際に、グローバル変数などを認識するために設定します。例えば、以下であれば、Browserが持つグローバル変数とES2021で定義されているグローバル変数を理解してくれます。

    "env": {
        "browser": true,
        "es2021": true
    },

例)no-undefルールを適用している場合

これは、定義されていない変数が使われていないかをチェックするルールです。何気なく使っているconsole.logなどは、Browserのグローバル変数として定義されています。

実際にチェックしてみましょう。
eslint-practiceプロジェクト配下にindex.tsを以下の内容で生成します。また.eslintrc.jsonも単純化します。

index.ts

console.log('test')

.eslintrc.json

{
    "env": {
        "browser": true
    },
    "extends": [
        "eslint:recommended"
    ]
}

Lintingを実行

# Lintingを実行
$ npx eslint index.ts
# 特にエラーは発生しません。

# 次に、"browser": trueを削除して実行してみてください。consoleが定義されていない旨のエラーメッセージが表示されます。
$ npx eslint index.ts
  1:1  error  'console' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)

consoleがどこから来たものなのかをESLintが理解できていないため、未定義変数として扱い、エラーが出力されていることが分かりますね。


ESLintルール群を継承することができます。「車輪の再開発はしない」が鉄則の業界なので、必ず便利なベストプラクティスが存在します。それを流用することができるプロパティとなります。npm packageとしてルール群をインストールすることも可能ですし、単純に相対パスを指定して、別の.eslintrc.jsonファイルを継承することも可能です。

以下は、eslintが推奨するルール群と、後ほど出てきますが、pluginsとして入れたルール群を継承していることを示します。

    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "plugin:@typescript-eslint/recommended"
    ],

動作はenvのときに実は確認済みで、no-undefというルールはeslint:recommendedに定義されているルールが利用されていました。

また上記の動作チェック時に、.eslintrc.jsonを簡略化した理由として、plugin:@typescript-eslint/recommendedが内部的にno-undefをoffにしていたため、eslint:recommendedのみをextendsに配置しました。


このプロパティは、"特定のファイル"に対して、ルール実行の挙動を変更するものです。したがって、filesプロパティを指定することが必須となります。

例)quotesルールの挙動を特定ファイルで変更したい場合

全体ルールとしては、ダブルクォーテーションはエラーですが、overrides内で指定されているfilesに対してはシングルクォーテーションがエラーとなります。

{
  "rules": {
    "quotes": ["error", "double"]
  },

  "overrides": [
    {
      "files": ["bin/*.js", "lib/*.js"],
      "excludedFiles": "*.test.js",
      "rules": {
        "quotes": ["error", "single"]
      }
    }
  ]
}

ESlintでチェックする対象をどのように解析するかを設定します。以下では、TypeScriptを解析できるように設定をおこなっています。Defaultでは、JavaScript ParserのEspreeが設定されています。

    "parser": "@typescript-eslint/parser",

例)TypeScriptのSyntaxをparser設定なしでチェックした場合

以下のようにindex.tsと.eslintrc.jsonを簡略化し、Lintingを実行してみてください。

index.ts

var str: string = 'test';

.eslintrc.json

{
    "extends": [
        "eslint:recommended"
    ],
    "parser": "@typescript-eslint/parser"
}

Lintingを実行

# TypeScriptが理解され、内容がチェックされていることが分かります。
$ npx eslint index.ts
  1:5  error  'str' is assigned a value but never used  no-unused-vars

✖ 1 problem (1 error, 0 warnings)

# 次に、"parser": "@typescript-eslint/parser"を削除して実行してみてください。
# 内容を解析できずにTypeを指定する":"でエラーが発生していることが分かります。
$ npx eslint index.ts
  1:8  error  Parsing error: Unexpected token :

✖ 1 problem (1 error, 0 warnings)

実はここでも、.eslintrc.jsonを簡略化した理由があります。
extendsにplugin:@typescript-eslint/recommendedが入っていると、この中の@typescript-eslint/parserが動作し、.eslintrc.jsonのparserの有無が関係なくTypeScriptのSyntaxが理解されてしまうので外しました。

ドキュメントでは、指定する必要が無いと記載されているので、継承されたものを暗黙的に利用するか、明示的に記載するかはどちらでも良いと思います。


JavaScript Syntaxをどのように解析するかを設定できます。また、これらの設定値を使う・使わないにかかわらず、parserプロパティに渡されます。

以下の設定では、最新のecmaサポートバージョンが設定され、ecmaモジュール(import、export形式)が問題なく解析されます。

    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },

ただし、Syntaxを解析するだけなので、例えば、es2021で追加されたグローバル変数を理解するには、別途、envにて、以下のように指定する必要があります。

実は、envで以下のように設定すると、暗黙的にparserOptionsのecmaVersionにes2021が設定されるので、parserOptionsを再設定する必要はありません。

    "env": {
        "es2021": true
    },

カスタム設定ファイルや、ルール、環境などが詰め込まれたもので、npm インストールにてプロジェクトに追加可能です。extendsに設定可能なルール群も同様にnpmパッケージにて共有されます。

pluginはpluginsへの設定だけでは効力が無く、plugins設定した上で、extendsやrulesに引用することができます。

extendsとpluginsを明確に切り分けようとすると混乱するので、pluginsはカスタム設定群で、その中からextendsにも設定できるし、rulesにも設定できる、柔軟性が高いものという認識でOKだと思います。

一応、違いについての参考記事です。
対比されているわけではなく、それぞれの特徴がピックアップされていますね。

    // 以下のようにplugin:xxxxをextendsに設定することで、
    // plugins内のカスタム設定ファイルを継承することができます。
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    "plugins": [
        "react",
        "@typescript-eslint"
    ],

ここまでの動作チェックでは、rulesが空にも関わらず、ESLintが動いてくれていたと思います。それは、extendsに設定してあるファイルにrulesがちゃんと設定してあったからです。

rulesに記載することで、extendsで継承された設定ファイル内に記載があるrulesを上書きしたり、pluginsからカスタムルールを適用させることが可能です。もちろん、ビルトインルールもあるので、extendsやplugins無しでもそれらのルールを適用させることもできます。

以下はビルトインルールを適用させる場合のrulesです。

{
    "rules": {
        "quotes": ["error", "double"]
    }
}

終わりに

今回は、あくまで公式ドキュメントをベースに動作チェックでざっくりと理解を深めました。
あとは、pluginsを自作すれば、完全な理解にいたりそうな気がしています。

参考

ESlint公式ドキュメント

extendsとplugins

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?