Rewrite `!key in col` ⇒ `!(key in col)`

JavaScript pattern

Negates key instead of the entire expression, which is likely a bug.

The intent is usually to negate the entire relation expression.

For !key in foo, operator precedence makes it equivalent to (!key) in foo and, type conversion makes it equivalent to (key ? "false" : "true") in foo.

For !obj instanceof Ctor, operator precedence makes it equivalent to (!obj) instanceof Ctor which is always false since boolean values are not objects.


Apply with the Grit CLI
grit apply no_unsafe_negation

Transforms when relational operator in is not encapsulated in an if statement

BEFORE
if (!key in foo) {
  foo();
}
AFTER
if (!(key in foo)) {
  foo();
}

Transforms when relational operator in is not encapsulated in an else if statement

BEFORE
if (!(key in foo)) {
  foo();
} else if (true && !key in bar) {
  foo();
}
AFTER
if (!(key in foo)) {
  foo();
} else if (true && !(key in bar)) {
  foo();
}

Transforms when relational operator instanceof is not encapsulated in an if statement

BEFORE
if (!obj instanceof Ctor) {
  foo();
}
AFTER
if (!(obj instanceof Ctor)) {
  foo();
}

Transforms when relational operator instanceof is not encapsulated in a ternary operation

BEFORE
!obj instanceof Ctor ? foo : bar;
AFTER
!(obj instanceof Ctor) ? foo : bar;

Does Not transform when type conversion is explicit

JAVASCRIPT
if ("" + !key in object) {
  // make operator precedence and type conversion explicit
  // in a rare situation when that is the intended meaning
}