fixhunt

eslint no-extra-boolean-cast

labelled safe
Runs / 2026-10-22T18-16-44-029Z-2211-eslint-no-extra-boolean-casteslint 9.39.52026-10-22 18:16 UTC8 programs × 2 round(s)16 programs, 4 fired, 4 fixed, 0 findings, 0 rejectedmodel cost $0.0028

Analysis Nemotron 3 Super

The rule flags unnecessary Boolean casts (!! or Boolean()) in contexts where values are automatically coerced to Boolean.

Fix: Removes the double negation (!!) or Boolean() call, keeping only the inner expression.

8 hazards
  • Rewriting !!foo to foo in a comma operator like (console.log(i), !!i < 10) changes evaluation order if foo has side effects, as the inner expression may no longer be evaluated.
  • Replacing Boolean(!!bar) with !!bar in a context like new Boolean(!!bar) alters behavior because new Boolean() creates an object wrapper, while !!bar is a primitive boolean.
  • Removing !! from !!foo in foo && !!bar ? baz : bat could change type coercion in the ternary branches if !!bar was ensuring a boolean for consistent comparison.
  • Stripping Boolean() from Boolean(bar ?? baz) in a logical expression may alter truthiness evaluation if bar or baz are objects with custom valueOf/toString methods that affect coercion differently than direct boolean conversion.
  • Deleting !! from !!expr in a return statement like return !!expr; is safe only if the function expects a boolean; removing it could return a truthy/falsy value instead of strict true/false, breaking strict equality checks elsewhere.
  • Removing !! from !!foo in a loop condition like for (; !!foo; ) may cause infinite loops if foo is an object that becomes false only after double negation due to [[ToBoolean]] quirks (though rare, theoretically possible with exotic objects).
  • Eliminating Boolean() from Boolean((bar, baz, !!bat)) in a comma operator could drop the side effect of evaluating !!bat if bat is undefined and the rewrite leads to parsing errors or unexpected values.
  • Applying the fix inside nested expressions like if ((!!foo || bar) && !!baz) when enforceForInnerExpressions is true may remove necessary casts if the outer context doesn't coerce to boolean, but the inner !! was for value consistency, not just final coercion.

Programs

idresulttitlehazard
r1-p001silent prediction offComment attachment during removalcomments attached to the removed or moved code
r1-p002silent prediction offTemporal Dead Zone via hoisting interactiontemporal dead zone after code is hoisted or reordered
r1-p003fix okSparse array indexingsparse arrays, holes, Array(n) vs [n], array-likes
r1-p004silent prediction off__proto__ key preservation__proto__ keys, prototype access, Object.assign vs spread
r1-p005fix okCoercion side effects in valueOf/toStringnumeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt
r1-p006silent prediction offnull vs undefined short-circuitnull/undefined distinction, optional chaining short-circuit, nullish vs falsy
r1-p007silent prediction offComma operator side effect lossEliminating Boolean() from Boolean((bar, baz, !!bat)) in a comma operator could drop the side effect of evaluating !!bat if bat is undefined and the rewrite leads to parsing errors or unexpected value
r1-p008fix okLabel and break interactionlabel/break/continue control flow, finally blocks, early returns in nested blocks
r2-p001silent prediction offComma Operator Side Effect LossRewriting !!foo to foo in a comma operator like (console.log(i), !!i < 10) changes evaluation order if foo has side effects, as the inner expression may no longer be evaluated.
r2-p002silent prediction offReturn Statement Boolean CastDeleting !! from !!expr in a return statement like return !!expr; is safe only if the function expects a boolean; removing it could return a truthy/falsy value instead of strict true/false, breaking s
r2-p003silent prediction offRegular Expressions Unicode and lastIndexregular expressions: escapes, unicode flag, lastIndex with the g flag
r2-p004silent prediction offStrict vs Sloppy Mode Semanticsstrict vs sloppy mode semantics
r2-p005fix okSparse Arrays Holes Array(n)sparse arrays, holes, Array(n) vs [n], array-likes
r2-p006silent prediction offComma Operator Bat Undefined Side EffectEliminating Boolean() from Boolean((bar, baz, !!bat)) in a comma operator could drop the side effect of evaluating !!bat if bat is undefined and the rewrite leads to parsing errors or unexpected value
r2-p007silent prediction offThis Binding Arrow Functionthis binding: arrow vs function, methods extracted from objects, call/apply/bind
r2-p008silent prediction offExceptions Inside Rewritten Codeexceptions thrown inside the code the fix removes or rewrites

Sources

r1-p001 · Comment attachment during removal
1// This comment should stay
2let x = !!/* keep-me */false;
3console.log(x);
false
r1-p002 · Temporal Dead Zone via hoisting interaction
1function f() {
2 console.log(typeof y);
3 let y = !!false;
4}
5f();
r1-p003 · Sparse array indexing
1const arr = Array(3);
2arr[1] = false;
3if (!!arr[0]) console.log('truthy'); else console.log('falsy'); // hole -> undefined
4console.log(arr.length);
--- orig.js	2026-10-22 14:16:53.003671515 -0400
+++ fixed.js	2026-10-22 14:16:56.454784753 -0400
@@ -1,4 +1,4 @@
 const arr = Array(3);
 arr[1] = false;
-if (!!arr[0]) console.log('truthy'); else console.log('falsy'); // hole -> undefined
+if (arr[0]) console.log('truthy'); else console.log('falsy'); // hole -> undefined
 console.log(arr.length);
falsy
3
r1-p004 · __proto__ key preservation
1const obj = { __proto__: null };
2obj.test = !!false;
3console.log(Object.hasOwn(obj, 'test'));
4console.log(obj.test);
true
false
r1-p005 · Coercion side effects in valueOf/toString
1const obj = {
2 valueOf() { return 0; }
3};
4if (!!obj) console.log('truthy'); else console.log('falsy');
--- orig.js	2026-10-22 14:16:53.004671548 -0400
+++ fixed.js	2026-10-22 14:16:55.359748756 -0400
@@ -1,4 +1,4 @@
 const obj = {
   valueOf() { return 0; }
 };
-if (!!obj) console.log('truthy'); else console.log('falsy');
+if (obj) console.log('truthy'); else console.log('falsy');
truthy
r1-p006 · null vs undefined short-circuit
1let v = undefined;
2console.log(!!v ?? 'default');
3v = null;
4console.log(!!v ?? 'default');
false
false
r1-p007 · Comma operator side effect loss
1let bat;
2let result = Boolean((console.log('side'), 1, !!bat));
3console.log(result); // Should log false and execute side effect
side
false
r1-p008 · Label and break interaction
1outer: {
2 if (!!false) break outer;
3 console.log('not reached');
4}
5console.log('done');
--- orig.js	2026-10-22 14:16:55.659758611 -0400
+++ fixed.js	2026-10-22 14:16:58.601855516 -0400
@@ -1,5 +1,5 @@
 outer: {
-  if (!!false) break outer;
+  if (false) break outer;
   console.log('not reached');
 }
 console.log('done');
not reached
done
r2-p001 · Comma Operator Side Effect Loss
1let i = 0;
2function logAndInc() {
3 console.log('side', i);
4 return i++;
5}
6if ((logAndInc(), !!logAndInc()) < 10) {
7 console.log('pass');
8} else {
9 console.log('fail', i);
10}
side 0
side 1
pass
r2-p002 · Return Statement Boolean Cast
1function getFlag() { return 1; }
2function check() { return !!getFlag(); }
3const r = check();
4console.log(typeof r, r === true ? 'strict true' : 'not strict');
boolean strict true
r2-p003 · Regular Expressions Unicode and lastIndex
1const re = /\u{61}/gu;
2re.lastIndex = 0;
3const str = 'a';
4const match = re.exec(str);
5console.log(match ? !!match[0] : null, match ? match.index : -1);
true 0
r2-p004 · Strict vs Sloppy Mode Semantics
1"use strict";
2function f() {
3 return !!arguments.callee;
4}
5try {
6 const r = f();
7 console.log(r);
8} catch (e) {
9 console.log(e.name, e.message);
10}
TypeError 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
r2-p005 · Sparse Arrays Holes Array(n)
1const arr = Array(3);
2arr[1] = 0;
3let sum = 0;
4for (let i = 0; i < arr.length; i++) {
5 if (!!arr[i]) sum += arr[i];
6}
7console.log(sum);
--- orig.js	2026-10-22 14:17:05.517085054 -0400
+++ fixed.js	2026-10-22 14:17:08.429182447 -0400
@@ -2,6 +2,6 @@
 arr[1] = 0;
 let sum = 0;
 for (let i = 0; i < arr.length; i++) {
-  if (!!arr[i]) sum += arr[i];
+  if (arr[i]) sum += arr[i];
 }
 console.log(sum);
0
r2-p006 · Comma Operator Bat Undefined Side Effect
1let bat;
2function log() { console.log('bat eval'); }
3const val = (() => {
4 const bar = 1, baz = 2;
5 return Boolean((bar, baz, !!bat));
6})();
7console.log(val);
false
r2-p007 · This Binding Arrow Function
1const obj = {
2 value: 42,
3 getValue: function() { return !!this.value; }
4};
5const fn = obj.getValue;
6console.log(fn());
false
r2-p008 · Exceptions Inside Rewritten Code
1function risky() {
2 throw new Error('boom');
3}
4try {
5 const result = !!risky();
6 console.log(result);
7} catch (e) {
8 console.log(e.name, e.message);
9}
Error boom