Open57

ESLintのルールを全部読む

pirosikickpirosikick

https://eslint.org/docs/latest/rules/

全部読んで、使うのか使わないのか、使うならどういう設定にするか、を全部考える。
airbnb-base を使いがちだったが自社のルールセット作るうえでは通ったほうが良い道なのではと思ったので、やる。

pirosikickpirosikick

array-callback-return

https://eslint.org/docs/latest/rules/array-callback-return

ArrayやArray.prototypeに生えている関数(Arrany.fromやArray.prototype.everyなど)が引数にcallbackを取る場合に、callbackで必ずreturnを書くことを強要するルール。

// だめな例
/*eslint array-callback-return: "error"*/

var indexMap = myArray.reduce(function(memo, item, index) {
    memo[item] = index;
    // returnがない
}, {});

var foo = Array.from(nodes, function(node) {
    if (node.tagName === "DIV") {
        return true;
    }
    // node.tagName !== "DIV"の場合にreturnがない
});

var bar = foo.filter(function(x) {
    if (x) {
        return true;
    } else {
        return; // returnはあるが返り値に一貫性がない
    }
});

Options

  • "allowImplicit"
    • default: false
    • trueの場合、返り値が必要なcallbackで、return;と書いて暗黙的にundefinedを返すのを許容する
  • "checkForEach"
    • default: false
    • trueの場合、Array.prototype.forEachのcallbackもこのルールの対象にする
  • "allowVoid"
    • default: false
    • trueの場合、Array.prototype.forEachのcallbackでreturn void;を許容する。
    • "allowVoid"は、"checkForEach"が有効な場合のみ、有効

俺の設定

optionsなしの"error"でよさそう。

pirosikickpirosikick

for-direction

https://eslint.org/docs/latest/rules/for-direction

forの継続条件と更新文が逆方向で無限ループになりそうな場合に指摘するルール。
eslint:recommendedに含まれている。

/*eslint for-direction: "error"*/
// 永遠に i < 10 なので無限ループ
for (var i = 0; i < 10; i--) {
}

// 永遠に i >= 10 なので無限ループ
for (var i = 10; i >= 0; i++) {
}

// 初期状態で i > 10 でないのでループしないはず。これも指摘してくれるの?
// 単純に条件と更新が合ってないから指摘してくれるだけかな、たぶん
for (var i = 0; i > 10; i++) {
}

// 条件文の左右が反対でもちゃんと指摘してくれるという例?
for (var i = 0; 10 > i; i--) {
}

// 変数でもいける?ええやん
const n = -2;
for (let i = 0; i < 10; i += n) {
}

Options

なし

俺の設定

"error"

pirosikickpirosikick

getter-return

https://eslint.org/docs/latest/rules/getter-return
eslint:recommendedに含まれている。

getterでreturnを強制するルール。
以下、怒られるコード例。

/*eslint getter-return: "error"*/

p = {
    get name(){
        // no returns.
    }
};

Object.defineProperty(p, "age", {
    get: function (){
        // no returns.
    }
});

class P{
    get name(){
        // no returns.
    }
}

Options

なし

俺の設定

TypeScriptを利用している場合は、TSのコンパイラーが指摘してくれるので無効にしても問題ないっぽいので、基本は"error"、TypeScriptには"off"でよさそう。

pirosikickpirosikick

no-async-promise-executor

https://eslint.org/docs/latest/rules/no-async-promise-executor
eslint:recommendedに含まれている。

new Promise(executor)のexecutorにasync functionを禁止するルール。
理由は以下。

  • async functionなexecutorがエラーを投げた場合、そのエラーはrejectを呼ばずにロストしてしまう。かなり、デバッグが難しい。
  • そもそも、new Promiseが不要。(async () { … })()で十分。

俺の設定

"error"

pirosikickpirosikick

no-await-in-loop

https://eslint.org/docs/latest/rules/no-await-in-loop

ループ内でawaitを許可しないルール。
ループ内にawaitがあると直列で処理してしまうので、Promise.allでやりましょう、みたいな感じ。

俺の設定

"error"にしておいて、並列で処理すると量が多すぎる場合や、途中で失敗した場合に他のリクエストを中止したい場合は/* eslint-disable no-await-in-loop */で都度無効にする対応がよさそう。
が、後者のケースを適切に処理してくれるnpmパッケージありそう。

pirosikickpirosikick

no-cond-assign

https://eslint.org/docs/latest/rules/no-cond-assign
eslint:recommendedに含まれる。

条件式で代入を禁止するルール。対象はif, for, while, do ... while。

Options

  • "except-parens"は、()で囲った場合のみOKとする。default値。
  • "always"は、常に許可しない。

俺の設定

"error"かな〜。"always"を付けるまではないか、という感じ。

pirosikickpirosikick

no-const-assign

https://eslint.org/docs/latest/rules/no-const-assign
eslint:recommendedに含まれる。

constで定義された変数に再代入市ている場合にエラーになるルール。ES2015未満の環境だと無視されるので。

俺の設定

"error"
TypeScriptの場合は、TSのコンパイラーが指摘するので"off"でよさそう。

pirosikickpirosikick

no-constant-condition

https://eslint.org/docs/latest/rules/no-constant-condition
eslint:recommendedに含まれている。

if (true)みたいな定数を条件文にしたらエラー。
if, for, while, do ... while、三項演算子が対象。

Options

  • checkLoops
    • defaultはtrue。falseの場合、ループ(for, while, do ... while)では許可。

俺の設定

"error"

pirosikickpirosikick

no-control-regex

https://eslint.org/docs/latest/rules/no-control-regex
eslint:recommendedに含まれている。

ASCIIの0~31は目に見えない制御文字で、それらが正規表現に入っている場合はエラーにするルール。JSでそれらの文字を滅多に使うことはないので、ミスだろうということ。

具体的に以下がエラー。

  • \x00 ~ \x1F
  • \u0000 ~ \u001F
  • \u{0} ~ \u{1F}
  • 上記を使わずに直接 U+0000 ~ U+001F を入力

俺の設定

"error"

pirosikickpirosikick

no-debugger

https://eslint.org/docs/latest/rules/no-debugger
eslint:recommendedに含まれている。

debugger命令を禁止するルール。昨今、デバッグ環境がよくなっていてあまり使われなくなっているし、本番環境にリリースしたら困るので、とのこと。

俺の設定

"error"

pirosikickpirosikick

no-dupe-args

https://eslint.org/docs/latest/rules/no-dupe-args
eslint:recommendedに含まれている。

関数の引数名が重複しているとエラー。
重複できることを知らなかった。。。以下の場合、2つ目のaが出力される。

functions hoge(a, b, a) {
  console.log(a);
}

hoge('a'); // undefined

俺の設定

"error"
TypeScriptの場合、TSのコンパイラーが許さないらしいので"off"でOK。

pirosikickpirosikick

no-duplicate-imports

https://eslint.org/docs/latest/rules/no-duplicate-imports

同じモジュールからのimport文が複数行ある場合にエラーになる。

// incorrect
import { merge } from 'module';
import something from 'another-module';
import { find } from 'module';

// correct
import { merge, find } from 'module';
import something from 'another-module';

Options

includeExports

defaultはfalse。trueの場合、export文もこのルールの対象になる。

/*eslint no-duplicate-imports: ["error", { "includeExports": true }]*/

// incorrect
import { merge } from 'module';
export { find } from 'module';

// correct
import { merge, find } from 'module';
export { find };

俺の設定

"error"

eslint-plugin-importやeslint-plugin-unused-importsとかでauto fixしてくれてた気もする。後で調べる。

pirosikickpirosikick

no-empty-character-class

https://eslint.org/docs/latest/rules/no-empty-character-class
eslint:recommendedに含まれる

正規表現で空の文字クラス(character class)がある場合、エラーになる。

// incorrect
var foo = /^abc[]/

制限事項

RegExpコンストラクタを使って文字列で正規表現を定義している場合、このルールでは検知できないので注意。

new RegExp("^abc[]")

俺の設定

"error"

pirosikickpirosikick

no-empty-pattern

https://eslint.org/docs/latest/rules/no-empty-pattern
eslint:recommendedに含まれている

空のdestructingをエラーにするルール。

// incorrect
var {} = foo;
var [] = foo;
var {a: {}} = foo;
var {a: []} = foo;
function foo({}) {}
function bar([]) {}
function baz({a: {}}) {}
function qux({a: []}) {}

Options

allowObjectPatternsAsParameters

defaultはfalse。trueの場合、関数の引数では許可する。ただし、関数の引数でも空の配列でdestructingするケースはエラー。

/*eslint no-empty-pattern: ["error", { "allowObjectPatternsAsParameters": true }]*/

// correct
function foo({}) {}
var bar = function({}) {};
var bar = ({}) => {};

// incorrect
function baz([]) {}

俺の設定

"error"

pirosikickpirosikick

no-ex-assign

https://eslint.org/docs/latest/rules/no-ex-assign
eslint:recommendedに含まれている

catchしたerrorにcatch内で代入している場合にエラーになる。

try {
    // code
} catch (e) {
    e = 10;
}

俺の設定

"error"

参考記事に貼られていたやつ

https://bocoup.com/blog/the-catch-with-try-catch

IE6~8でcatchに変数のスコープがないので、catchした変数と同名の変数が上位のスコープにある場合、その変数にcatchしたエラーを代入しちゃうらしい。
もはや関係ないと思うけど、へーである。

pirosikickpirosikick

no-fallthrough

https://eslint.org/docs/latest/rules/no-fallthrough
eslint:recommendedに含まれる。

switch文でfallthrough(breakせずに次のcaseに繋げる)を禁止するルール。

Options

commentPattern

特定のコメントがある場合にルールを無視させるオプション。

/*eslint no-fallthrough: ["error", { "commentPattern": "break[\\s\\w]*omitted" }]*/

switch(foo) {
    case 1:
        doSomething();
        // break omitted

    case 2:
        doSomething();
}

allowEmptyCase

空のケースはOKにするルール。

俺の設定

"error"

pirosikickpirosikick

no-func-assign

https://eslint.org/docs/latest/rules/no-func-assign

eslint:recommendedに含まれる。

FunctionDeclaration(function foo() { ... })で定義された関数の他の変数への代入を禁止するルール。
TSではコンパイラーがチェックしてくれているらしいので、このルールを無効にしても大丈夫とのこと

function foo() {}
foo = bar; // error

俺の設定

"error"

pirosikickpirosikick

no-import-assign

https://eslint.org/docs/latest/rules/no-import-assign

eslint:recommendedに含まれる。

import文よって束縛した変数に対する代入、インクリメントおよびデクリメントの禁止。
TSではコンパイラーが警告してくれるので、このルールは無効にしてもOK。ただ、Object.assignを使って代入するケースはTSでもカバーできない、とのこと。

import mod, { named } from "./mod.mjs"
import * as mod_ns from "./mod.mjs"

mod = 1          // ERROR: 'mod' is readonly.
named = 2        // ERROR: 'named' is readonly.
mod_ns.named = 3 // ERROR: The members of 'mod_ns' are readonly.
mod_ns = {}      // ERROR: 'mod_ns' is readonly.
// Can't extend 'mod_ns'
Object.assign(mod_ns, { foo: "foo" }) // ERROR: The members of 'mod_ns' are readonly.

俺の設定

"error"

pirosikickpirosikick

no-inner-declarations

https://eslint.org/docs/latest/rules/no-inner-declarations

ブロック内での変数・関数の定義を禁止するルール。
ES6前後で挙動が変わる部分で、ES6以降 or "use strict"利用時はそこまで気にしなくてよい(スコープについて考えたのが久々すぎる)ので無効でもよさそう

俺の設定

設定しなくてよい。

pirosikickpirosikick

no-invalid-regexp

https://eslint.org/docs/latest/rules/no-invalid-regexp
eslint:recommendedに含まれる。

RegExpコンストラクタで指定する正規表現が構文的におかしい場合にエラーになるルール。
RegExpコンストラクタの第2引数のフラグは、最新のECMAScriptに準拠しており、パーサーの設定は見てないので注意。オプションのallowConstructorFlagsを使って、利用可能なフラグを指定することも可能。

俺の設定

"error"

pirosikickpirosikick

no-irregular-whitespace

https://eslint.org/docs/latest/rules/no-irregular-whitespace
eslint:recommendedに含まれる。

以下の文字が含まれていた場合にエラーになるルール。目視だと分かりづらく、バグったときに発見しづらい文字。

\u000B - Line Tabulation (\v) - <VT>
\u000C - Form Feed (\f) - <FF>
\u00A0 - No-Break Space - <NBSP>
\u0085 - Next Line
\u1680 - Ogham Space Mark
\u180E - Mongolian Vowel Separator - <MVS>
\ufeff - Zero Width No-Break Space - <BOM>
\u2000 - En Quad
\u2001 - Em Quad
\u2002 - En Space - <ENSP>
\u2003 - Em Space - <EMSP>
\u2004 - Three-Per-Em
\u2005 - Four-Per-Em
\u2006 - Six-Per-Em
\u2007 - Figure Space
\u2008 - Punctuation Space - <PUNCSP>
\u2009 - Thin Space
\u200A - Hair Space
\u200B - Zero Width Space - <ZWSP>
\u2028 - Line Separator
\u2029 - Paragraph Separator
\u202F - Narrow No-Break Space
\u205f - Medium Mathematical Space
\u3000 - Ideographic Space

オプションを使うと、特定の場面ではルールを無効にすることもできる。

  • skipStrings trueの場合、文字列定義内では許可(デフォルトで有効)
  • skipComments trueの場合、コメント内では許可
  • skipRegExps trueの場合、正規表現リテラル内では許可
  • skipTemplates trueの場合、テンプレートリテラル内では許可
  • skipJSXText trueの場合、JSX Text内では許可

俺の設定

"error"

pirosikickpirosikick

no-misleading-character-class

https://eslint.org/docs/latest/rules/no-misleading-character-class
eslint:recommendedに含まれる。Suggestions対応ルール。

正規表現に複数のコードポイントを組み合わせた文字が含まれている場合に教えてくれるルール。
正規表現の文字クラスは、複数のコードポイントで作られた文字を扱えない。

/^[👶🏻]$/u.test("👶🏻"); //→ false
/^[👶🏽]$/u.test("👶🏽"); //→ false

オプション

allowEscape

trueの場合、\uXXXXで記述している場合は許可。

俺の設定

"error"

pirosikickpirosikick

no-obj-calls

https://eslint.org/docs/latest/rules/no-obj-calls
recommendedに含まれる。

ESが提供するグローバルオブジェクトで、コンストラクタとして利用できないものをコンストラクタや関数として呼び出そうとするとエラーになるルール。

  • ES5: Math, JSON
  • ES2015: Reflect
  • ES2017: Atomics
  • ES I18n: Intl

TypeScriptを利用している場合、TSのコンパイラがエラーを吐くのでこのルールは無効にしてもOK。

俺の設定

JSでは"error"。TSでは指定しない。

pirosikickpirosikick

no-promise-executor-return

https://eslint.org/docs/latest/rules/no-promise-executor-return
Suggestions対応ルール。

Promiseのexecutorで値をreturnするのを禁止するルール。
new Promiseでコンストラクタの引数に渡す関数を、executorと呼ぶらしい。executorで値をreturnしても無視されるだけなので、このルールが教えてくれる。

オプション

allowVoid

trueの場合、voidは許可。

俺の設定

"error"

pirosikickpirosikick

no-prototype-builtins

https://eslint.org/docs/latest/rules/no-prototype-builtins
recommendedに含まれるルール。Suggestions対応ルール。

hasOwnPropertyなどObject.prototypeに生えているメソッドをobj.hasOwnProperty(...) のようにオブジェクトのメソッドとして呼ぶのを禁止するルール。
どういうときに困るかというと、例えばJSON.parseでJSON文字列からオブジェクト生成する場合に{"hasOwnProperty":1}のようなデータが入っていると、obj.hasOwnProperty(...)はクラッシュしてしまう。Object.prototype.hasOwnProperty.call(obj, ...)で呼びましょう、という昔からある教え。

俺の設定

"error"

pirosikickpirosikick

no-self-assign

https://eslint.org/docs/latest/rules/no-self-assign
recommendedに含まれるルール。

両サイド同じ変数の代入を禁止するルール。

foo = foo
[bar, baz] = [bar, baz]

オプション

props

trueの場合、プロパティへの代入は許可。

// ["error", {"props": true}] の場合、以下はOK
obj.a = obj.a;

俺の設定

"error"

pirosikickpirosikick

no-self-compare

https://eslint.org/docs/latest/rules/no-self-compare

両サイドが全く同じ場合の比較を禁止するルール

x === x

NaNかどうか判定する方法(NaN同士は===で比較してもfalseになる)として利用することが唯一有効な利用方法だが、Number.isNaNを使う方が意図が明確でよいと思うので、禁止でよい。

俺の設定

"error"

pirosikickpirosikick

no-setter-return

https://eslint.org/docs/latest/rules/no-setter-return
recommendedに含まれる。

Setterで値をreturnするのを禁止するルール。
Setterで値をreturnしても無視されるだけなので。
TypeScriptの場合、コンパイラーがエラーにしてくれるので、このルールは無効にしてもOK.

俺の設定

JSでは"error"、TSでは指定しない・無効にする。

pirosikickpirosikick

no-sparse-arrays

https://eslint.org/docs/latest/rules/no-sparse-arrays
recommendedに含まれる

sparse arrayを禁止するルール。
sparse arrayとは、以下のように配列リテラル内にカンマだけ書いて、まばらな(sparse)な状態の配列のこと。

items = [,,] // length === 2。 items[0]、items[1]はundefined。

※個人的な感想:[,,]で要素2つなの、直感的じゃなくね?と思ったが、[]が0, [,]が1, [,,]が2, ... と考えると自然だった。

以下のように値がある要素とない要素を混ぜることができるが、これが意図お通りなのかタイポなのか、判断が難しいので、禁止でよいと思う。

var colors = [ "red",, "blue" ];

最後にカンマがあるパターンは、無視される。(これも意味ないと思うから、エラーでいいのでは?)

[1, 2, ] // これはエラーにならない。length === 2になるので。

俺の設定

"error"

pirosikickpirosikick

no-undef

https://eslint.org/docs/latest/rules/no-undef
recommendedに含まれる。

未定義の変数へアクセスするのを禁止するルール。
/* globals: ... */コメントか、ESLintのglobalsで指定した変数は対象外。

このルールはread-onlyなグローバル変数への代入を禁止しないので、禁止したい場合は、別途no-global-assignルールが必要。
また、このルールはグローバル変数への再定義も禁止しないので、禁止したい場合はno-redeclareルールが必要。
TypeScriptの場合、コンパイラーがこのルールを代替してくれるので、指定しなくてもOK。

オプション

typeof

trueの場合、typeof内でグローバル変数を指定すると警告してくれる。デフォルトはfalse。

俺の設定

JSの場合は"error"、TSの場合は無指定 or 無効。

pirosikickpirosikick

no-unexpected-multiline

https://eslint.org/docs/latest/rules/no-unexpected-multiline
recommendedに含まれる。

自動セミコロン挿入にならない改行を禁止するルール。
JSではセミコロンは任意で、省略した場合に改行時に自動でセミコロンが挿入された状態と解釈される仕様だが、例外があって、改行した2つの文が結合した状態で解釈される場合がある。
え、その例外って何、って?それは自分で調べる方があなたのためになると思いますし、このルールを有効にすればそんなこと考えなくてよいのでおすすめです。

俺の設定

"error"

pirosikickpirosikick

no-unmodified-loop-condition

https://eslint.org/docs/latest/rules/no-unmodified-loop-condition

ループの条件内の変数がループ内で変更されていない場合にエラーになるルール。

以下のように、関数呼び出しの引数に使われている場合も「変更されていない」判定になり、エラーになる。

// 以下はエラー
while (node) {
    doSomething(node);
}

俺の設定

"error"

ループ内で変更している方がコードとしてわかりやすいし、変更しないようなコードを書いたことが今まで無いので、recommendedには入ってないらしいがエラーでいいと思う。

pirosikickpirosikick

no-unreachable

https://eslint.org/docs/latest/rules/no-unreachable
recommendedに含まれる。

return, throw, continue, break以降の到達することのないコードを禁止するルール。
以下のような、サブクラスのconstructorでsuper()を呼ばない場合のフィールド定義もunreachableなのでエラーになる。フィールドはsuper()呼び出し後にインスタンスに追加されるため。

/*eslint no-unreachable: "error"*/

class C extends B {
    #x; // unreachable
    #y = 1; // unreachable
    a; // unreachable
    b = 1; // unreachable

    constructor() {
        return {};
    }
}

TypeScriptにおいては、tsconfig.jsonでallowUnreachableCode: falseにすると、TSコンパイラーでのこのチェックを行ってくれる。
https://www.typescriptlang.org/tsconfig/#allowUnreachableCode

俺の設定

JSの場合は"error"
TSの場合は@tsconfig/strictestを使うことが多く、allowUnreachableCode: falseになっているので指定なし・無効、でよさそう。
https://github.com/tsconfig/bases/blob/694a3683ac2a85ee7cbe461a7510a4d794ff885b/bases/strictest.json#L5

pirosikickpirosikick

no-unreachable-loop

https://eslint.org/docs/latest/rules/no-unreachable-loop

1度しかbody部が実行されないループを禁止するルール。
(静的コードパス解析での指摘で制限があるので、recommendedに入ってない?)

オプション

ignores

このルールを無効にするループを指定できる。

俺の設定

"error"

pirosikickpirosikick

no-unsafe-finally

https://eslint.org/docs/latest/rules/no-unsafe-finally
recommendedに含まれる

unsafeなfinallyを禁止するルール。
finally内でのreturn, throw, break, continueの呼び出しは、try/catch内でのそれらの呼び出しを上書きしてしまうので、意図しない挙動になる可能性が高い。

// We expect this function to return 1;
(() => {
    try {
        return 1; // 1 is returned but suspended until finally block ends
    } catch(err) {
        return 2;
    } finally {
        return 3; // 3 is returned before 1, which we did not expect
    }
})();

// > 3

俺の設定

"error"

pirosikickpirosikick

no-unsafe-negation

https://eslint.org/docs/latest/rules/no-unsafe-negation
recommendedに含まれる。Suggestions対応されている。

比較演算の左オペランドで否定を使うのを禁止するルール。
例えば、!key in objectは、key in objectの否定とは評価されず、keyを否定したものをin objectで評価する。!(key in object)のように書く必要がある。
TypeScriptではコンパイラが指摘してくれるので、無効にしてもOK。

オプション

(WIP)

俺の設定

JSでは"error"、TSでは指定しないor無効にする。
(が、TSではfixまでやってくれないとしたら有効にしといてもいいか🤔)

pirosikickpirosikick

no-unsafe-optional-chaining

https://eslint.org/docs/latest/rules/no-unsafe-optional-chaining
recommendedに含まれる。

undefinedが許与されないコンテキストでOptional Chainingするのを禁止するルール。

1 in obj?.foo;  // TypeError
with (obj?.foo);  // TypeError
for (bar of obj?.foo);  // TypeError
bar instanceof obj?.foo;  // TypeError
const { bar } = obj?.foo;  // TypeError

var obj = undefined;
(obj?.foo)(); // TypeError
(obj?.foo).bar; // TypeError

オプション

disallowArithmeticOperators

trueの場合、算術演算でOptional Chainingを使うのを禁止する。undefinedと算術演算すると、結果がNaNになるため。
デフォルトはfalse。

// obj?fooがundefinedの場合、結果がNaNになる
obj?.foo + bar;

俺の設定

["error", { disallowArithmeticOperators: true }]

TSで警告してくれそうな予感がしたが、特に記述なかったので気になった🤔

pirosikickpirosikick

no-unused-vars

https://eslint.org/docs/latest/rules/no-unused-vars
recommendedに含まれる。

宣言したが使われていない値を禁止するルール。おなじみのルール。

exportedコメント

CommonJS・ES Module環境以外では、varはグローバル変数を定義するのに利用できる。
/* exported 変数名 */で、そのようなグローバルに定義されている値を指定でき、このルールの対象外にできる。
ま、CommonJS・ES Module以外の環境で開発することはあんまりないと思うけど!

Options

vars

"all" or "local"
"all"がデフォルトで、全ての値がこのルールの対象になる。"local"の場合は、ローカル変数のみを見て、グローバル変数は見ない。

varsIgnorePattern

varで定義する値の中で、このルールの対象外にするパターンを正規表現で指定できる。

args

"after-used", "all" or "none"

after-used
利用されている引数のうち、最後に定義されている引数より後ろにある引数のみをこのルールの対象にする。
下記コードでは、barより後ろの引数(baz, qux)がエラーになる。

/*eslint no-unused-vars: ["error", { "args": "after-used" }]*/

// 2 errors, for the parameters after the last used parameter (bar)
// "baz" is defined but never used
// "qux" is defined but never used
(function(foo, bar, baz, qux) {
    return bar;
})();

all
全ての引数をチェック。

none
引数をチェックしない。

argsIgnorePattern

チェックしない引数のパターンを正規表現で指定できる。例えば、_で始まる引数は無視するとか。/*eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }]*/

caughtErrors

"all" or "none"
catchブロックで捕捉したエラーをチェックするかどうか。"all"はチェックする、"none"はチェックしない。
"all"がデフォルト。

caughtErrorsIgnorePattern

catchブロックで捕捉したエラーの中で、無視するパターンを正規表現で指定できる。

destructuredArrayIgnorePattern

配列の分割代入で、このルールが無視するパターンを正規表現で指定できる。

ignoreRestSiblings

デフォルトはfalse。trueの場合、Object rest propertyを無視する。
var { foo, ...rest } = data; みたいなときに、fooを除くプロパティをrestに入れたいという要件の場合、fooはただ捨てたいだけでエラーがノイズになる。そういうときに有用。

ignoreClassWithStaticInitBlock

デフォルトはfalse。
trueの場合、Static initialization blockをルールの対象外にする。

reportUsedIgnorePattern

デフォルトはfalse。
trueの場合、varsIgnorePattern, argsIgnorePattern, caughtErrorsIgnorePattern, destructuredArrayIgnorePatternで指定したパターンにマッチした部分をレポートしてくれる。

俺の設定

とりあえず、"error"
v0.0.9からあるルールだけあって、オプションが多いのでどれかが必要になる可能性もありそう。

pirosikickpirosikick

no-use-before-define

https://eslint.org/docs/latest/rules/no-use-before-define
値を定義前に使うのを禁止するルール。おなじみ。

Options

functions

関数をこのルールの対象にするか、どうか。デフォルトはtrue

classes

クラスをこのルールの対象にするかどうか。デフォルトはtrue

variables

値をこのルールの対象にするかどうか。デフォルトはtrue

allowNamedExports

trueの場合は、export { … };をこのルールの対象外とする。

These references are safe even if the variables are declared later in the code.

とのこと。
MDNにも以下のように記述されている。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export

エクスポート宣言は一時的なデッドゾーンのルールには従いません。X という名前自体が宣言される前に、そのモジュールが X をエクスポートすることを宣言することができます。

デフォルトはfalse。

俺の設定

["error", { allowNamedExports: true }]

pirosikickpirosikick

no-useless-backreference

https://eslint.org/docs/latest/rules/no-useless-backreference
recommendedに含まれる。

backreference=後方参照。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Regular_expressions/Backreference

後方参照は、前回キャプチャグループによって一致したのと同じテキストに一致する方法です。

/(b)\1/i.test("bB"); // true

以下のような、ECMAScriptの仕様的には正しいがマッチしない後方参照を禁止するルール。

  • 論理和内の後方参照(ex: /(a)|\1b/)
  • グループより先にある後方参照(ex: /\1(a)/)
  • グループ内の後方参照(ex /(\1)/)
  • 否定の先読みないにあるグループの後方参照(ex: /a(?!(b)).\1/)

俺の設定

"error"

pirosikickpirosikick

require-atomic-updates

https://eslint.org/docs/latest/rules/require-atomic-updates

awaitやyieldによるレースコンディションを招く代入を禁止するルール。
例えば、以下のコード。

let totalLength = 0;

async function addLengthOfSinglePage(pageNum) {
  totalLength += await getPageLength(pageNum);
}

Promise.all([addLengthOfSinglePage(1), addLengthOfSinglePage(2)]).then(() => {
  console.log('The combined length of both pages is', totalLength);
});

上記コードの最終的なtotalLengthの値は、await getPageLength(1) + await getPageLength(2)になる気がする。しかし、totalLength += await getPageLength(pageNum);は、まずtotalLengthをreadするため、実際はtotalLength = 0 + await getPageLength(pageNum)と同義になる。結果として、getPageLength(1)getPageLength(2)の2つの中で後でresolveした方が最終的なtotalLengthの値になってしまう。

上記のコードでrace conditionを避けるためには、以下のようにawait後にtotalLengthをreadするようにする。

// totalLengthをawaitの後でreadするように変える
totalLength = await getPageLength(pageNum) + totalLength;

// こちらでもOK
const length = await getPageLength(pageNum);
totalLength += length;

または、以下のようにtotalLengthがimmutableになるようにコードを書く(個人的には絶対こっち)。

Promise.all([getPageLength(1), getPageLength(2)]).then(pageLengths => {
  const totalLength = pageLengths.reduce((accumulator, length) => accumulator + length, 0);

  console.log('The combined length of both pages is', totalLength);
});

具体的にどのような場合にエラーになるか

変数への代入の場合

async関数 or generator関数内で、以下のような実行フローを検出した場合にエラーになる。

  1. 変数のread
  2. yield or awaitにより関数が中断
  3. 関数が再開後、1の変数に値を代入

以下の場合はエラーにならない。

  • 2と3の間で変数Aを再度readしている
  • 関数Bが中断している間に変数Aにアクセスできない(例: 変数Aがローカル変数)

以下、怒られるコード例。

/* eslint require-atomic-updates: error */

let result;

async function foo() {
    result += await something; // error
}

async function bar() {
    result = result + await something; // error
}

async function baz() {
    result = result + doSomething(await somethingElse); // error
}

async function qux() {
    if (!result) {
        result = await initialize(); // error
    }
}

function* generator() {
    result += yield; // error
}

プロパティへの代入の場合

async関数 or generator関数内で、以下のような実行フローを検出した場合にエラーになる。

  1. 変数またはオブジェクトのプロパティのread
  2. yield or awaitにより関数が中断
  3. 関数が再開後、オブジェクトのプロパティに値を代入

変数代入と似ているけど、3の代入が必ずしも1のプロパティと同じである必要がないので、より厳格。
例えば、以下のコード。obj.doneのread後(①)、await getSomething()で関数が中断(②)、obj.somethingawait getSomething()の返り値を代入(③)しているため、エラーになる。
理由は、await getSomething()で関数を中断している間にobj.doneの値が変わる可能性があるから。

/* eslint require-atomic-updates: error */

async function foo(obj) {
    if (!obj.done) {
        obj.something = await getSomething(); // error
    }
}

以下が正しいコード。これは気づくのが難しいので、ありがたいかもしれない。

/* eslint require-atomic-updates: error */

async function foo(obj) {
    if (!obj.done) {
        const tmp = await getSomething();
        if (!obj.done) {
            obj.something = tmp;
        }
    }
}

Options

allowProperties

trueの場合、「プロパティへの代入」をこのルールの対象外にできる。デフォルトはfalse。

俺の設定

"error"