Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Opt-out of Confusing use of '!'. #455

Closed
3rd-Eden opened this issue Feb 13, 2012 · 41 comments
Closed

Opt-out of Confusing use of '!'. #455

3rd-Eden opened this issue Feb 13, 2012 · 41 comments
Milestone

Comments

@3rd-Eden
Copy link

This check was added for issue #211 but there is no way to opt-out of this detection. As the original poster of that issue suggested, it should be enabled by default, but with an override.

@valueof
Copy link
Member

valueof commented Feb 13, 2012

Could you give us a valid usage example, please?

@goatslacker
Copy link
Member

#211 (comment)

I'm also curious about the IE6 sniffing.

@valueof
Copy link
Member

valueof commented Mar 5, 2012

Closing this ticket since we didn't get any valid usage example. Feel free to re-open it later.

@valueof valueof closed this as completed Mar 5, 2012
@mar10
Copy link

mar10 commented Apr 21, 2012

Is

if( !!a === !!b ){  

a valid sample (typecast operands to bool)?
I find this more concise than

if( (a && b) || (!a && !b) ) {

@goatslacker goatslacker reopened this Apr 22, 2012
@goatslacker
Copy link
Member

Yeah that'd good.

@mar10
Copy link

mar10 commented Apr 22, 2012

The samples from issue #211 are still valid, i.e. 'confusing' or even dangerous.
I am not sure if opt-out is the best solution, or if `!!x' should be considered valid?

@axkibe
Copy link

axkibe commented May 15, 2012

if (!(mseq <= this.messages.length)) { throw new Error('invalid mseq: ' + mseq); }

This one will nicely throw an Error when mseq is not a number as well if its greater than this.messages.length

@jsoverson
Copy link

Came here with a use case similar to @axkibe. The inverted case won't catch both range and invalid data errors at once.

This doesn't strike me as bad practice considering the resulting code is readable and direct in its intention.

@npup
Copy link

npup commented Sep 11, 2012

jshint's killer feature is the opt-out, as opposed to crockford-ed-in.

@chadaustin
Copy link

For clarity, in our unit test, I have assert.greater et al defined as such:

        greater: function(lhs, rhs) {
            if (!(lhs > rhs)) {
                fail(new AssertionError(repr(lhs) + ' not greater than ' + repr(rhs)));
            }
        },

        less: function(lhs, rhs) {
            if (!(lhs < rhs)) {
                fail(new AssertionError(repr(lhs) + ' not less than ' + repr(rhs)));
            }
        },

        greaterOrEqual: function(lhs, rhs) {
            if (!(lhs >= rhs)) {
                fail(new AssertionError(repr(lhs) + ' not greater than or equal to ' + repr(rhs)));
            }
        },

        lessOrEqual: function(lhs, rhs) {
            if (!(lhs <= rhs)) {
                fail(new AssertionError(repr(lhs) + ' not less than or equal to ' + repr(rhs)));
            }
        },

I wrote it that way for clarity and would appreciate an opt-out for this warning.

@jakub-g
Copy link

jakub-g commented Nov 20, 2012

+1 from my side for an opt-out (we're caught at !!a == !!b).

@jakub-g
Copy link

jakub-g commented Nov 20, 2012

BTW, this seems to be a duplicate: #578

@popham
Copy link

popham commented May 18, 2014

This is an error, not a warning. By the doc-comments of the closing commit, warnings can be ignored, but not errors.

@siemiatj
Copy link

So what should I do instead of if (!(event.which == ESCAPE_KEY)) { according to your best practices ?

@rwaldron
Copy link
Member

Why would you ever write that?

What's wrong with being clear about the program's intention?

if (event.which !== ESCAPE_KEY) {...}

@siemiatj
Copy link

Not my code, dunno the intentions. I found it in some lib and jshint was not validating it because of that.

@rwaldron
Copy link
Member

Why are you linting 3rd party library code? Isn't that the author's job?

@chadaustin
Copy link

Whether or not !(a == b) is ugly or not, there should be an opt-out, right? I thought the philosophy of jshint was to provide an opt-out for every warning.

Personally, in the case of test framework assertions, I found it clearer to write the conditional to match the assertion:

function assertEqual(x, y) {
    if (!(x == y)) { ... }

function assertNotEqual(x, y) {
    if (!(x != y)) { ... }

function assertGreater(x, y) {
    if (!(x > y)) { ... }

@micchickenburger
Copy link

How about this example?

if ( !((end - start) % 2) ) // do stuff

I could create a variable to hold this value, but why? To me, this doesn't seem like a confusing use of the NOT operator so it should not throw an error.

@rwaldron
Copy link
Member

rwaldron commented Sep 5, 2014

Why do you need to be "clever" here? What's wrong with just writing what you actually mean? (a - b) % 2 === 0

@rwaldron
Copy link
Member

rwaldron commented Sep 5, 2014

If someone wants to write I patch, I will gladly review it for inclusion, but until then I don't want to read another comment on this thread. Less talking, more doing. We can discuss whatever patch comes along as much as the author or contributors and interested parties would like.

jugglinmike pushed a commit to jugglinmike/jshint that referenced this issue Oct 21, 2014
This commit adds special syntax to the /*jshint directive making it
possible to ignore any warnings (but not errors). For example:

	/*jshint -W121 */

	var a = 12.;

The code above would raise a trailing dot warning but '-W121' suppresses
it. For advanced use only.

Closes jshintGH-578.
Closes jshintGH-455.
Closes jshintGH-624.
Closes jshintGH-683.
Closes jshintGH-699.
Closes jshintGH-755.
@ghost
Copy link

ghost commented Nov 10, 2014

I have a use case. I'm retrieving a value from a database that should be a boolean, but it comes back as either '0' or '1'. I'm making the conversion with !!+val, which converts to number and then to boolean, but produces this jshint warning. Adding parens does not silence the warning. No warning occurs with !!val but this is not correct because '0' unlike 0 is truthy. I've wound up just disabling W018 for the line in question.

@iki
Copy link

iki commented Mar 11, 2015

+1 for optout, !!x is a valid use case and common idiom for converting to bool as @mgoldWork and @jakub-g pointed out

@kosich
Copy link

kosich commented Mar 19, 2015

+1 for !!a === !!b

@iki
Copy link

iki commented Mar 24, 2015

actually !!x can be used anywhere for converting to bool...

could it be marked as valid construct in jshint (with no optout needed), @valueof?

@mjhm
Copy link

mjhm commented Mar 25, 2015

+1 for opt out

@cjc343
Copy link

cjc343 commented Mar 27, 2015

It's great when the first Google result for a problem is a closed issue with no solution.

Per #780, this option can be disabled/enabled with the not-at-all-cryptic /*jshint -W018 */ and /*jshint +W018 */

+1 for a more cryptic opt-out.

@callumlocke
Copy link

@cjc343 thanks.

there should be a way to opt out from .jshintrc too.

whenever someone asks for a way to opt out of something, people always come back with "but why would you ever want to write that, that's bad bad code". this is never a valid response to someone asking for an opt-out. if they're asking for an opt-out, they disagree with you that it's 100% always bad, and that's that. jshint is supposed to help us, not get in the way. everything should be opt-out-able. absolutely everything.

@ghost
Copy link

ghost commented Apr 8, 2015

What is the .jshintrc field to allow confusing use of !?

For example, the following is giving me the warning:

function even(n) {
  return !(n % 2)
}

@sigod
Copy link

sigod commented May 6, 2015

+1 for opt out

@sigod
Copy link

sigod commented May 6, 2015

Could you give us a valid usage example, please?

console.assert(!!prototype === !!object, 'invalid state', prototype, object);

@bitdivine
Copy link

+1. Here is one of my common use cases:

// Note: points is an array, each having latitude and longitude
var dataset = {};
points.forEach(function(point){
    if (!(dataset.latMin<point.lat)) dataset.latMin = point.lat;
});

Note that !(dataset.latMin<point.lat) is not the same as dataset.latMin>=point.lat when the LHS is undefined.

@lukeapage
Copy link
Member

Note that !(dataset.latMin<point.lat) is not the same as dataset.latMin>=point.lat when the LHS is undefined.

Isn't that confusing for the poor person reading the code?

Anyway, this has been merged into #780 where it is noted you can use W018 to disable this warning.

@qm3ster
Copy link

qm3ster commented Jan 5, 2016

if (data === undefined || (!(data.length > 0))) 

is considered confusing. so is

if (data === undefined || !(data.length > 0)) 

Wat do?

@jugglinmike
Copy link
Member

Have you tried

-if (data === undefined || !(data.length > 0)) 
+if (data === undefined || data.length <= 0) 

...although a property name like length makes me suspect that data.length === 0 may suffice.

@qm3ster
Copy link

qm3ster commented Jan 5, 2016

It's not equivalent, because for a non-array object with no length property your examples give false.
Now I realize there are also strings with the default "length" property so I may have to check for type first, as well -.-

@bitdivine
Copy link

Whether or not ** is ugly or not, there should be an opt-out, right?

Yes. I'm not sure why this is being discussed.

@ghost
Copy link

ghost commented Feb 7, 2016

!! is the easiest way to convert "anything" into "bool". +1 for opt-out

@JohnCoker
Copy link

The case I keep running into is wanting to test if something is not a positive number:
if (!(n > 0))
Otherwise, one needs to write something like:
if (typeof n != 'number' || isNaN(n) || n <= 0)

@rogercoder
Copy link

The case I keep running into is wanting to test if something is not a positive number:
if (!(n > 0))
Otherwise, one needs to write something like:
if (typeof n != 'number' || isNaN(n) || n <= 0)

This is exactly why I came here wondering why jshint was keeping me from writing code the way I want.

@nicolo-ribaudo
Copy link
Contributor

!(n > 0) and typeof n != 'number' || isNaN(n) || n <= 0 aren't the same thing:

var n = "1";
console.log(!(n > 0)); // false
console.log(typeof n != 'number' || isNaN(n) || n <= 0) // true

Anyway, you can just use -W018 to disable the warning

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests