じゅえり〜だんごのぶろぐ

ITエンジニアがIT情報や資格勉強など幅広い分野から、日々のトレンドまでを「昔の自分に教えてあげたい!!」をテーマに情報発信していきます

【備忘録】三項演算子がESLint Rule no-unused-expressionsでエラーとなる

Angular製のアプリを作成しているときに、三項演算子がESLint Ruleのno-unused-expressionでエラーになりました。その原因と対処方法を備忘録として残します。なお、この現象に対して、Angular製というのは関係がないため、記事では簡単なTypeScriptのソースコードで説明します。

発生した現象

ESLintのrulesで、no-unused-expressionsが有効になっているとき、

module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint"
    ],
    "rules": {
        "no-unused-expressions": ["error"]
    }
};

こんな感じで、条件分岐の短縮として三項演算子を使用すると、

const temperature = 25;

temperature >= 25 ? console.log('暑いですね') : console.log('普通ですね');

error Expected an assignment or function call and instead saw an expressionとエラーになります。

 $ npx eslint test.ts

  3:1  error  Expected an assignment or function call and instead saw an expression  no-unused-expressions

✖ 1 problem (1 error, 0 warnings)

そもそもno-unused-expressionsとは

eslint.org

An unused expression which has no effect on the state of the program indicates a logic error.

For example, n + 1; is not a syntax error, but it might be a typing mistake where a programmer meant an assignment statement n += 1; instead. Sometimes, such unused expressions may be eliminated by some build tools in production environment, which possibly breaks application logic.

すごく簡単に説明すると、n + 10;というどこにも代入していないようなコードはコンパイルエラーにはならないけど、不具合などの原因になる可能性があるから禁止しますね。というルールになります。

なぜ三項演算子でエラーになるのか

結論から言うと、三項演算子はif文とは違い、変数に代入ができる式(Expression)であり、no-unused-expressionsは使用されていない(変数への代入が行われていない)式をエラーとするからです。

jsprimer.net 上記の記事では、文(Statement)とは、末尾に;がつき、変数に代入ができないもの、式(Expression)とは変数に代入できるものとあります。 つまり、文(Statement)であるif文は変数に代入することができず、式(Expression)である三項演算子は変数に代入することができます。

const test1 = if(temperature >= 25){ return '暑いですね。' } else { return ' 寒いですね。'} // エラー
const test2 = temperature >= 25 ? '暑いですね' : '普通ですね'; // エラーではない

そして、no-unused-expressionsは使用されていない式、つまりどこにも代入されていない式をエラーとして判定するため、結果を変数に格納していない三項演算子はエラーと判定されてしまいます。

対処法

三項演算子の結果を変数に格納し使用する

三項演算子の結果を変数に格納したり、別のメソッドの引数にすることでエラーを回避できます。

const temperature = 25;

console.log(temperature >= 25 ? '暑いですね' : '普通ですね');

三項演算子ではなく、if-else文を使用する

三項演算子を使用せずにif-else文を使用することで、エラーを回避できます。

const temperature = 25;

if (temperature >= 25) {
    console.log('暑いですね');
} else {
    console.log('普通ですね');
}

no-unused-expressionsのオプション allowTernaryをtrueにする

no-unused-expressionsには結果の代入を行わない三項演算子を許可するオプションallowTernaryが存在します。 allowTernarytrueにすることで三項演算子を許可します。

"rules": {
    "no-unused-expressions": ["error", { "allowTernary": true }]
}

おわりに

no-unused-expressionsのルールが存在すると考えると、三項演算子をif文の短縮形として使用するのがそもそも間違いなのかもしれません。このエラーについて調べるにあたり、文(Statement)と式(Expression)の違いについても知ることになり、とても勉強になりました。