Require or disallow Yoda Conditions (yoda)

Yoda conditions are so named because the literal value of the condition comes first while the variable comes second. For example, the following is a Yoda condition:

if ("red" === color) {
    // ...
}

This is called a Yoda condition because it reads as, “red is the color”, similar to the way the Star Wars character Yoda speaks. Compare to the other way of arranging the operands:

if (color === "red") {
    // ...
}

This typically reads, “color is red”, which is arguably a more natural way to describe the comparison.

Proponents of Yoda conditions highlight that it is impossible to mistakenly use = instead of == because you cannot assign to a literal value. Doing so will cause a syntax error and you will be informed of the mistake early on. This practice was therefore very common in early programming where tools were not yet available.

Opponents of Yoda conditions point out that tooling has made us better programmers because tools will catch the mistaken use of = instead of == (ESLint will catch this for you). Therefore, they argue, the utility of the pattern doesn’t outweigh the readability hit the code takes while using Yoda conditions.

Rule Details

This rule takes one argument. If it is "never" then comparisons must never be a Yoda condition. If "always", then the literal must always come first. The default is "never".

The following patterns are considered warnings:

if ("red" === color) {
    // ...
}
if (true == flag) {
    // ...
}
if (5 > count) {
    // ...
}
if (-1 < str.indexOf(substr)) {
    // ...
}
// When ["always"]
if (color == "blue") {
    // ...
}
if (0 <= x && x < 1) {
    // ...
}

The following patterns are not considered warnings:

if (5 & value) {
    // ...
}
if (value === "red") {
    // ...
}
// When ["always"]
if ("blue" == value) {
    // ...
}
// When ["always"]
if (-1 < str.indexOf(substr)) {
    // ...
}

Options

There are a few options to the rule:

"yoda": [2, "never", {
    "exceptRange": false,
    "onlyEquality": false
}]

The onlyEquality option is a superset of exceptRange, thus both options are hardly useful together.

Range Tests

“Range” comparisons test whether a variable is inside or outside the range between two literals. When configured with the exceptRange option, range tests are allowed when the comparison itself is wrapped directly in parentheses, such as those of an if or while condition.

"yoda": [2, "never", { "exceptRange": true }]

With the exceptRange option enabled, the following patterns become valid:

function isReddish(color) {
    return (color.hue < 60 || 300 < color.hue);
}
if (x < -1 || 1 < x) {
    // ...
}
if (count < 10 && (0 <= rand && rand < 1)) {
    // ...
}
function howLong(arr) {
    return (0 <= arr.length && arr.length < 10) ? "short" : "long";
}

Apply only to equality, but not other operators

Some developers might prefer to only enforce the rule for the equality operators == and ===, and not showing any warnings for any code around other operators. With onlyEquality option, these patterns will not be considered warnings:

if (x < -1 || 9 < x) {
}
if (x !== 'foo' && 'bar' != x) {
}

Further Reading

Version

This rule was introduced in ESLint 0.7.1.

Resources