ESLint

ESLint v5.0.0 変更点まとめ (随時更新)

v4.19.0 | 次 (未定)

ESLint 5.0.0-rc.0 がリリースされました。

5.0.0 正式リリースまで随時この記事を更新していきます。

このリリースには後方互換性のない変更が含まれています (Migration guide (英語))。ESLint の利用者にとって特に影響が大きいと思われる変更は以下の 6 つです。

また、プラグイン・カスタム ルールの開発者は以下の変更にもご注意ください。


質問やバグ報告等ありましたら、お気軽にこちらまでお寄せください。

🏢 日本語 Issue 管理リポジトリ
👫 日本語サポート チャット
🏢 本家リポジトリ
👫 本家サポート チャット

🏁 リリース スケジュール

  • 2018/03/31 JST ... 5.0.0 α0 リリース (Blog post)
  • 2018/04/14 JST ... 5.0.0 α1 リリース (Blog post)
  • 2018/04/28 JST ... 5.0.0 α2 リリース (Blog post)
  • 2018/05/12 JST ... 5.0.0 α3 リリース (Blog post)
  • 2018/05/28 JST ... 5.0.0 α4 リリース (Blog post)
  • 2018/06/09 JST ... 5.0.0 RC リリース (Blog post)
  • 2018/06/23 JST ... 5.0.0 正式リリース
  • 進捗状況
  • 現在 ESLint 5.0.0 はリリース候補版であるため、インストール時に next タグを指定する必要があります。 npm install --save-dev eslint@next

💥 利用者向けの非互換な変更点

#10009: eslint CLI コマンドの exit code が変更されました。

従来はエラー無しのとき 0, それ以外のとき 1 でした。
今回の変更で、静的検証自体に失敗した場合の exit code が 2 になりました。

  • 0 ... 静的検証に成功し、検証ルールがエラーを報告しなかった。
  • 1 ... 静的検証に成功し、検証ルールが何らかのエラーを報告した。
  • 2 ... 静的検証に失敗した (.eslintrcファイルにエラーがある、バグによる内部エラー、など)。

失敗時の exit code が 12 になるので、exit code が 1 かどうかチェックしている場合に対応が必要です。

#10074: Node.js 4.x, 5.x, 7.x のサポートを終了しました。

Node.js 4 LTS のサポート期間が終了しました (5.x と 7.x のサポート期間は既に終了しています)。これに合わせて ESLint も Node.js 4 のサポートを終了しました。

ESLint 5.0.0 では Node.js ^6.14.0 || ^8.10.0 || >=9.10.0 をサポートします。つまり、LTS である 6.x と 8.x の修正時点のパッチバージョン以降と、修正時点の最新バージョンである 9.10.0 より新しいものをサポートします。

引き続き Node.js 4 でも利用したい場合は、ESLint 5.0.0 への移行をお控えください。
あるいは、非サポートの Node.js でのテスト時は動作しないよう if-node-version のようなツールをご利用ください。

#10119: no-unused-vars ルールの挙動が変更されました。

no-unused-vars ルールの引数に関するデフォルトの挙動が変更されました。

これまでは「最後の引数が未使用だった場合に最後の引数だけを警告」していましたが、ESLint 5.0.0 からは「使用している引数より後ろにあるすべての未使用引数を警告」するようになります。

/*eslint no-unused-vars: error */

function f(a, b, c, d) { // 従来は d だけ警告されていたが、今後は c と d が警告される。
    return b
}

#10143: eslint CLI コマンドに与えたファイルパス (or glob) にマッチするファイルが存在しない場合にエラーを投げるようになりました。

これまで、ファイルパスの typo 等で存在しないファイルを検証しようとした場合、ESLint は正常終了していました。そのため、ファイルが存在しない場合と検証エラーが無い場合の区別がつけられませんでした。

今回の変更で、ファイルが存在しなかった場合にエラーが投げられるようになります。

ファイルが存在しないパスを eslint コマンドに渡している場合、対応が必要になります。

#10152,#10230: parserOptions.ecmaFeatures.experimentalObjectRestSpread オプションを使うと非推奨警告が表示されるようになりました。

ESLint のデフォルトの構文解析器は非標準の Rest/Spread Properties 構文を使うための ecmaFeatures.experimentalObjectRestSpread オプションを持っていました。しかし、ECMAScript 2018 で Rest/Spread Properties 構文が正式採用されたため、このオプションは役目を終えました。

ESLint 5 で parserOptions.ecmaFeatures.experimentalObjectRestSpread オプションが指定された場合、非推奨警告が表示され、 parserOptions.ecmaVersion:2018 が自動付与されます。

parserOptions.ecmaVersion オプションに置き換えてください。

もし、引き続き Rest/Spread Properties 以外の ES2018 構文をエラーにしたい場合、eslint-plugin-es を利用してください。

#10158: eslint:recommended が含むルールセットが更新されました。

ESLint 4.x で追加されたルールのうち 2 つが新たに有効になります。

eslint:recommended 設定を利用していて上記 2 つのルールによる警告が新たに発生した場合、コードを修正するか、手動でルールを無効にしてください。

#10210: グローバル変数の定義が更新されました。

browser, node, jest のグローバル変数の定義が更新されました。

以下の変数定義は削除されます。
browser:
                AutocompleteErrorEvent: false,
                CDATASection: false,
                ClientRect: false,
                ClientRectList: false,
                CSSAnimation: false,
                CSSTransition: false,
                CSSUnknownRule: false,
                CSSViewportRule: false,
                Debug: false,
                DocumentTimeline: false,
                DOMSettableTokenList: false,
                ElementTimeControl: false,
                FederatedCredential: false,
                FileError: false,
                HTMLAppletElement: false,
                HTMLBlockquoteElement: false,
                HTMLIsIndexElement: false,
                HTMLKeygenElement: false,
                HTMLLayerElement: false,
                IDBEnvironment: false,
                InputMethodContext: false,
                MediaKeyError: false,
                MediaKeyEvent: false,
                MediaKeys: false,
                opera: false,
                PasswordCredential: false,
                ReadableByteStream: false,
                SharedKeyframeList: false,
                showModalDialog: false,
                SiteBoundCredential: false,
                SVGAltGlyphDefElement: false,
                SVGAltGlyphElement: false,
                SVGAltGlyphItemElement: false,
                SVGAnimateColorElement: false,
                SVGAnimatedPathData: false,
                SVGAnimatedPoints: false,
                SVGColor: false,
                SVGColorProfileElement: false,
                SVGColorProfileRule: false,
                SVGCSSRule: false,
                SVGCursorElement: false,
                SVGDocument: false,
                SVGElementInstance: false,
                SVGElementInstanceList: false,
                SVGEvent: false,
                SVGExternalResourcesRequired: false,
                SVGFilterPrimitiveStandardAttributes: false,
                SVGFitToViewBox: false,
                SVGFontElement: false,
                SVGFontFaceElement: false,
                SVGFontFaceFormatElement: false,
                SVGFontFaceNameElement: false,
                SVGFontFaceSrcElement: false,
                SVGFontFaceUriElement: false,
                SVGGlyphElement: false,
                SVGGlyphRefElement: false,
                SVGHKernElement: false,
                SVGICCColor: false,
                SVGLangSpace: false,
                SVGLocatable: false,
                SVGMissingGlyphElement: false,
                SVGPaint: false,
                SVGPathSeg: false,
                SVGPathSegArcAbs: false,
                SVGPathSegArcRel: false,
                SVGPathSegClosePath: false,
                SVGPathSegCurvetoCubicAbs: false,
                SVGPathSegCurvetoCubicRel: false,
                SVGPathSegCurvetoCubicSmoothAbs: false,
                SVGPathSegCurvetoCubicSmoothRel: false,
                SVGPathSegCurvetoQuadraticAbs: false,
                SVGPathSegCurvetoQuadraticRel: false,
                SVGPathSegCurvetoQuadraticSmoothAbs: false,
                SVGPathSegCurvetoQuadraticSmoothRel: false,
                SVGPathSegLinetoAbs: false,
                SVGPathSegLinetoHorizontalAbs: false,
                SVGPathSegLinetoHorizontalRel: false,
                SVGPathSegLinetoRel: false,
                SVGPathSegLinetoVerticalAbs: false,
                SVGPathSegLinetoVerticalRel: false,
                SVGPathSegList: false,
                SVGPathSegMovetoAbs: false,
                SVGPathSegMovetoRel: false,
                SVGRenderingIntent: false,
                SVGStylable: false,
                SVGTests: false,
                SVGTransformable: false,
                SVGTRefElement: false,
                SVGURIReference: false,
                SVGViewSpec: false,
                SVGVKernElement: false,
                SVGZoomAndPan: false,
                SVGZoomEvent: false,
                TimeEvent: false,
                XDomainRequest: false,
                XMLHttpRequestProgressEvent: false,
                XPathException: false,
                XPathNamespace: false,
                XPathNSResolver: false
node:
                arguments: false,
                GLOBAL: false,
                root: false
jest:
                check: false,
                gen: false

#10335: 複数行に跨がる/*eslint-disable-line*/コメントが警告を生成するようになりました。

ESLint v4.18.0 から単一行のブロックコメントで eslint-disable-lineeslint-disable-next-line をサポートしています (それ以前は行コメント (//eslint-disable-line等) のみサポートしていました)。

これらのコメントは1行だけ ESLint の警告を無効化する機能であるため、複数行に跨がるブロックコメントで eslint-disable-lineeslint-disable-next-line を書いても、単に無視されていました。

今回の変更で、単に無視する代わりに無視されていることを知らせる警告を生成するようになりました。

複数行に跨がるブロックコメントに eslint-disable-lineeslint-disable-next-line を書いていた場合、それらを削除してください。

#10337: いくつかのルールのデフォルトの振る舞いが変更されました。

2つのルールのデフォルトの振る舞いが変更されました。

  • object-curly-newline ... デフォルトで consistent オプションが有効になります。
  • no-self-assign ... デフォルトで props オプションが有効になります。

これらのルールを利用している場合、新しい振る舞いに沿うようにコードを修正する必要があるかもしれません。
または、元の振る舞いに戻すために設定ファイルにて各オプションに false を設定してください。

💥 プラグイン開発者向けの非互換な変更点

#10008: RuleTester が厳密な等号比較を利用するようになりました。

RuleTester は、これまで内部的に assert.equalassert.deepEqual を使っていましたが、assert.strictEqualassert.deepStrictEqual を使うように変更されました。

ルールのテストで暗黙の型変換に頼っていた場合は、テストが失敗するようになりました。

暗黙の型変換に頼らないようにテストを修正する必要があります。

#10013: 空白・コメントのみのソースコードに対して検証を行うようになりました。

これまで、空白・コメントのみのソースコードは検証されず、必ずエラー無しになっていました。
今回の変更で普通に検証するようになりました。

空のファイルで正常に動作しないルールがある場合、対応が必要です。

#10014: AST ノードが常に parent プロパティを持つようになりました。

この修正は ESLint v4.7.0 で実施されたものの、動作しなくなるプラグインがあったため差し戻されていたものです。

これまで、ESLint は AST をトラバースしながら各ノードに parent プロパティを設定していました。そのため、より後方にあるノードでは parent プロパティが正常に設定されておらず、バグの原因になることがありました。

今回の変更で、あらかじめ全ノードに parent プロパティを設定してからトラバースするようになりました。

parent プロパティの有無に依存したルールがある場合、対応が必要です。

#10057: メッセージのないエラー報告が例外を投げるようになりました。

context.reportメソッドは、以下のようなメッセージがないエラー報告で例外を投げるようになりました。

context.report({ node, message: "" });

エラーメッセージを必ず指定してください。

#10152: JSX 構文内の文字列を表す AST ノードが Literal から JSXText に変更されました。

JSX の仕様変更によるものです。

JSX を扱うルールについて、対応が必要になります。

#10209: context._linter プロパティが削除されました。

このプロパティは非公開 API でしたが、eslint-plugin-eslint-comments プラグインが機能実現のために利用していたため互換性のために残されていました。この非公開 API に依存するプラグイン ルールは --report-unused-disable-directives CLI オプションで代用可能なので、この非公開 API は削除されました。

eslint-plugin-eslint-comments プラグインの no-unused-disable ルールを使用している場合は、これを削除して代わりに --report-unused-disable-directives CLI オプションを利用するか、eslint-plugin-eslint-comments プラグインを v3.0.0 β に更新してください。

eslint-plugin-eslint-comments プラグインの著者 (私) のように context._linter プロパティに依存したルールを保守している場合は修正が必要です。

#10252,#10270: context.getScope() メソッドの振る舞いが変更されました。

この修正は本質的にバグ修正ですが、3年以上同じ動作をしていた context.getScope() メソッドの動作が変化するため、Breaking Change として扱われています。以下の3種類の修正があります。

  1. #10245 scope.type === "TDZ" であるスコープ オブジェクトが削除されました。そのようなスコープ オブジェクトは for-infor-of 構文があると作られていました。しかし、静的解析でそれを作成するのは妥当ではないことと、それを作ることによってバグの原因になっていたため削除されました。
  2. #10246 ForStatement, ForInStatement, ForOfStatement ノードで context.getScope() を呼んだとき、scope.type === "for" であるスコープ オブジェクトを返すようになりました。ESLint 4.x 以前はその for スコープの親のスコープを返していました (バグ)。
  3. #10247 context.getScope() メソッドが parserOptions.ecmaVersion オプションを参照しなくなりました。そのオプションの有無にかかわらず、常に同じ動作をするようになります。parserOptions は構文解析器が定義するオプションで、babel-eslint, typescript-eslint-parser, vue-eslint-parser のような ecmaVersion オプションを持たない構文解析器も存在します。そういった構文解析器を使っている場合、常に ES5 と同じ動作をしていました (バグ)。

context.getScope() を利用しているルールを保守している場合、影響がないかをご確認ください。

💥 連携ツール開発者向けの非互換な変更点

#9692: require("eslint").linter は列挙されなくなりました。

Node API の require("eslint").linter プロパティは、ESLint 4.0.0 から非推奨になっています。代わりに require("eslint").Linter クラスを利用してください。

今回の変更により、Object.keys(require("eslint")) 等で linter が列挙されなくなりました。

#10012: 個々の検証エラーの結果から source プロパティが削除されました。

報告された検証エラーは報告されたコードを含む source プロパティを持っていますが、この source プロパティは ESLint v3.8.0 から非推奨になっていました。今回、この source プロパティが削除されました。

個々の検証エラーの source プロパティに依存している場合、トップレベルの source プロパティを使うよう修正する必要があります。

🚀 本体への機能追加

#9664: JSXFragment 構文をサポートしました。

JSXFragment 構文をサポートしました。

<>foo</>

#9905: プラグインが npm スコープをサポートしました。

以下のように @scope と記述すると、@scope/eslint-plugin が読み込まれるようになりました。

.eslintrc.json
{
    "plugins": ["@scope"]
}

#10191: CLIEngine のコンストラクタ引数に globInputPaths オプションが追加されました。

ESLint に与えられたファイルパスは、基本的に Glob パターンとして扱われて実際のファイルに解決されます。ところで、パスがすべて実ファイルを指していることが予め分かっている場合、このファイル解決処理をスキップすることで 20% 前後の性能向上が期待できる場合があるそうです。

新たに追加された globInputPaths オプションを使うことで、Glob パターンの解決処理をスキップすることができます。

"use strict"

const { CLIEngine } = require("eslint")
const linter = new CLIEngine({ globInputPaths: false })

linter.executeOnFiles("path/to/file.js") // OK
linter.executeOnFiles("path/to/*.js") // This glob pattern will not be resolved.

#10353: eslint --initnpm install を実行しない選択肢を追加しました。

主に yarn 利用者向けです。

💡 新しいルール

#9955: prefer-object-spread

Object.assign 関数を警告し、Spread properties 構文を利用するよう提案するルールです。

/*eslint prefer-object-spread: error */

//✘ BAD
const obj1 = { a: 1, b: 2 }
const obj2 = Object.assign({ x: 0 }, obj1)

//✔ GOOD
const obj3 = { x: 0, ...obj1 }

#10163: max-classes-per-file

1ファイルに書くことができるクラス定義の数を制限するスタイル・ルールです。
デフォルトでは1個までに制限されます。

/*eslint max-classes-per-file: error */

//✘ BAD
class A {}
class B {}
/*eslint max-classes-per-file: error */

//✔ GOOD
class A {}

🔧 オプションが追加されたルール

#10220: valid-jsdoc requireParamType

JSDoc コメントにて、仮引数の型を省略することを許可するオプションが追加されました。
TypeScript や Flow と併用する場合に便利でしょう。

/*eslint valid-jsdoc: [error, { requireParamTypes: false, requireReturnType: false }] */

//✓GOOD

/**
 * Add two numbers.
 * @param num1 The first number.
 * @param num2 The second number.
 * @returns The sum of the two numbers.
 */
function add(num1: number, num2: number): number {
    return num1 + num2;
}

#10355: array-element-newline consistent

配列のカッコの内側のどちらか一方でも改行があった場合に、両方改行するオプションが追加されました。

//✗BAD
const a = [1, 2, 3
]
const a = [
    1, 2, 3]

//✓GOOD
const a = [1, 2, 3]
const a = [
    1, 2, 3
]

#10373: camelcase ignoreDestructuring

分割代入時に非キャメルケースを許可するオプションが追加されました (なんでだろ?)。

/*eslint camelcase: [error, { ignoreDestructuring: true }]*/

//✓GOOD
let { category_id: categoryId } = query; // もともとOK
let { category_id: category_id } = query; // 新しいオプションでOK

✒️ eslint --fix をサポートしたルール

#10040: one-var

var a;
var b;

// は以下のように自動修正されます。

var a, b;