8

In if statement's casting to a Boolean via double negation (!!) is unnecessary, because these if statements, for example, are equivalent:

if (!!foo) {
    // ...
}

if (foo) {
    // ...
}

But what if casting to a Boolean via !! is in return statement? Like here:

nameToSomething : function(someName){
            if (someName) {
                return !!this._var[someVar] ? this._var: undefined;
            }
            return undefined;
        },

!!this._mServicesByName[someName] in return is the same as this._mServicesByName[someName] here? Why?

An explanation in plain English why it is different/the same as well as examples how to circumvent this rule in JavaScript, so my linter will not "see" it will be very appreciated.

Many thanks in advance.

Ilya Dachkovsky
  • 335
  • 1
  • 3
  • 13
  • Well it coerces to a Boolean, and returning a Boolean is quite different to returning an Object property? – dsgriffin Apr 27 '15 at 13:30
  • It should be rather obvious, if you need a boolean value you can coerce it with a double logical not operator. If you just need a falsy or truthy value, you don't have to coerce anything. If you want to be fancy you can do bitwise instead `~~sServiceName` – adeneo Apr 27 '15 at 13:31
  • @adeneo Well, not as obvious for a beginner :-) I need a Boolean in return statement. But my linter considers it an error. So can I do instead of "return !!this._mServicesByName[someName]" something like this: "var x = !!_mServicesByName" and then "return this.x[somename]"? – Ilya Dachkovsky Apr 27 '15 at 13:40
  • @dsg My guess is not very different, but I'm not sure. Since the question :-) – Ilya Dachkovsky Apr 27 '15 at 13:44
  • Your linter isn't really that important, there's no reason `!!func` isn't valid. – adeneo Apr 27 '15 at 13:44

2 Answers2

8

Ok, I've done some research myself since asking this and actually stumbled upon some very similar questions (with answers) to the double negative trick in JavaScript. Here and here I found some explanation of the need of double boolean negative trick itself. To cut the long story short it's like casting in Java. !! expression is used when you actually need to return a boolean without changing true and false. Its' a non inverted boolean or simply saying, true boolean representation.

For example this !true will be false as well as vice versa !false will be true. But by simply using !!true and !!false you can get the same true and false without changing result and still work with boolean. The same is true for !!0 being false and !!1 being true.

Now, back to my question. In the code snippets above I can't omit non inverted boolean because the functions given as examples are expecting a boolean. And false can't be change to true and vice versa. Neither it can't be replaced with a bitwise operator, because in this case it will not work. Creating a new variable above the function holding non inverted boolean an help silencing my linter, though. So it might be an answer solve the problem.

Or, alternately, changing the linter options for the "no-extra-boolean" rule in IDE will be a much better decision ) Because in JavaScript, as I learnt, they are used often and there is no way around it. It's not even a bad practice. Sometimes, when you need a true boolean representation, it's a very convenient way to write a code. And the only one.

Community
  • 1
  • 1
Ilya Dachkovsky
  • 335
  • 1
  • 3
  • 13
4

I am not totally clear on what your question is but in reference to linter errors of 'no-extra-boolean-cast' it is telling you that the !! is unnecessary in both of your cases.

You mention !!this._mServicesByName[someName] in return is the same as this._mServicesByName[someName] but in your code: return !!this._var[someVar] ? this._var: undefined; that is not what you are doing. You have a ternary statement whose first parameter is automatically cast as a boolean so you linter should correctly throw an error.

This is unnecessary:

`return !!this._var[someVar] ? this._var: undefined;`

And should just be:

`return this._var[someVar] ? this._var: undefined;`

As they are equivalent.

This, however, is a valid use of the boolean cast:

`return !!this._var[someVar]; // Returns value cast as true/false

Because it's not at all the same as:

`return this._var[someVar]; // Returns unmodified value
cyberwombat
  • 38,105
  • 35
  • 175
  • 251