How can I suppress warnings for using '!!' (not not)? - javascript

In my project jshint complains about !! I need to convert a string to a boolean value
var x = 'true';
if ( !!x === true ) { ... }
So, jshint throws the following problem:
line 35 col 20 Confusing use of '!'.
What jshint-option should I disable to allow this? Or is that not possible?

It looks like the problem is with ===. Simply
if (!!x )
works fine.
I think the "confusing" part is that !!foo === bar is hard to parse priority-wise (is it (!!foo)==bar or !(!foo==bar)?).

This particular "feature" has caused so much pain in the community.
You can disable it by putting this in your .jshintrc config file.
{
"-W018": true
}

WARNING: this is not going to evaluate the way you want it to
var myBool = Boolean("false"); // == true
var myBool = !!"false"; // == true
if you don't want jshint to yell at you, also you don't need to have === when comparing bool == is the same. though if you are making a bool value you should not need to compare it at all.
if(myBool)
{
//some code here
}
or
if(!myBool)
{
//some code here
}
to get the value as a bool you prob want to just do a string comparison
var mybool = aString == "true";
that should get you what you are looking for then you can just:
if(myBool)
{
//some code here
}

To really answer this question, not providing workarounds, disabling this error in jshint can be done by
-W018

Related

Returning false if variable doesn't exist

I have some code structured like this but with a bunch of variables with paths of various depths within dict that may or may not exist:
var dict = {
'test1': 'test',
'test2': ['testa', 'testb'],
}
var test_path1 = dict['test2']['testa'] ? test_path1: false
var test_path2 = dict['test3']['testz'] ? test_path2: false
console.log(test_path2)
Basically my program creates a bunch of arrays that it saves within user_dict depending on user input. Later I need to process dict and check some of the variables to see their values, or whether or not they exist.
I can't even get to that point though, since defining test_path2 returns "cannot read property testz of undefined."
I thought using ? test_path2: false would work, but I still get that same error.
Someone suggested using optional chaining, but that doesn't seem like a good solution since some of my variables are located within 4-5 nested objects/arrays, each of which may or may not exist.
What's the best way to handle this? Is there an error with my syntax or am I approaching the problem the wrong way? All I need is for test_path1 and test_path2 to return false if it doesn't exist.
Arguably, the best way to handle this (while keeping legacy compatibility) is using get from lodash:
import { get } from 'lodash';
const result = get(dict, ['test2', 'testa']) || false;
// or
const result = get(dict, 'test2.testa') || false;
Note: to only import get (and nothing else) from lodash, use lodash-es instead of lodash. In other words, by using lodash-es you enable tree-shaking lodash at build step.
or you could simply check each level:
const result = dict && dict.test2 && dict.test2.testa || false;
If legacy compatibility is not an issue, you could use optional chaining, as suggested in Noriller's answer.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
optional chaining can and will work even on deep nested objects
to top it off, you can use the nullish coalescing to return a "default" (fale in your case)
var test_path1 = dict['test2']?.['testa'] ?? false
this will return the value or false if it is undefined
You can use some modern javascript features. Try Optional Chaining:
var dict = {
'test1': 'test',
'test2': { 'testa': 'testb' },
}
var test_path1 = dict['test2']?.['testa'] || false
var test_path2 = dict['test3']?.['testz'] || false
console.log(test_path1, test_path2)
If you want to write more optimistic code you could also use a try catch at some point in the code.
try {
return dict.test1.test2
} catch (e) {
if (e instanceof TypeError)
return false
throw e
}
This prevents the need for writing code that does null checks.

Type error: Object is possibly 'null'. TS2531 for window.document

I am adding TypeScript to my project for the first time.
Using window.document.getElementById() to access something results in the error:
Type error: Object is possibly 'null'. TS2531
I searched online but couldn't come to the best solution for this. window can never be null.
TS is doing its job and tells you that window.document.getElementById("foobar") COULD return something that is null.
If you are absolutely sure that #foobar element DOES exist in your DOM, you can show TS your confidence with a ! operator.
// Notice the "!" at the end of line
const myAbsolutelyNotNullElement = window.document.getElementById("foobar")!
Or, you can add a runtime nullable check to make TS happy
const myMaybeNullElement = window.document.getElementById("foobar")
myMaybeNullElement.nodeName // <- error!
if (myMaybeNullElement === null) {
alert('oops');
} else {
// since you've done the nullable check
// TS won't complain from this point on
myMaybeNullElement.nodeName // <- no error
}
window.document.getElementById("foobar");
Is either returning a HTMLElement or null
As you might used a similar statement before: window.document.getElementById("foobar").value
Typescript is complaining about, that value might not be accessible and you should explicitly check this before.
To avoid this you can do the following:
const element = window.document.getElementById("foobar");
if (element !== null) {
alert(element.value);
}
It is because you have to set the type.
const checkbox = document.getElementById("toggleFilter") as HTMLInputElement
checkbox.checked = true
Here you have to make sure your window.document.getElementById("id_name")! is set. You can try this
const element = window.document.getElementById("id_name");
if(element){
console.log(element);
}
Typescript is complaining that object, result of window.document.getElementById execution in your case, can be null.
This could be turned off using strictNullChecks flag in your tsconfig.json which I do not recommend.
Alternatively you can do checks at suggested in other answers or starting with Typescript 3.7 use Optional Chaining syntax to make your code more concise:
obj?.doSometething(); //good, will not do something.
obj?.prop = 'plop'; //not good because it does not work with assignments.
add this. ( ? ) in array, Example:
form.get('description')?.errors

shorten javascript code - check if property exists and is not empty [duplicate]

This question already has answers here:
Test for existence of nested JavaScript object key
(64 answers)
Closed 6 years ago.
Is it possible to shorten this code?
var access_followup = user_access && user_access.followup && user_access.followup.access ? true : false;
Unfortunately JS does not have a null conditional operator. You could write helper function for it or use a slightly less effective method of creating dummy objects:
var access_followup = !!((user_access || {}).followup || {}).access;
which is shorter and prevents using the property names more than once, but doesn't improve readability. The !! is used to enforce a boolean value even when the values don't exist
Maybe I am answering the wrong thing, but why would you want to make it shorter? I'd vote to make it a bit longer, but easier to read for people who work with your code ( including you :) ).
You could make it more readable by splitting it up into multiple lines:
var access_followup = (
user_access &&
user_access.followup &&
user_access.followup.access === true // if access is a boolean value
);
Or, in case you really really want to have short code and you do not use a minifier already, you can try https://jscompress.com/ (which actually compresses any code you paste into it! but makes it WAY less readable).
If the first 2 checks are because you are protecting against exception thrown when user_access.followup is undefined, you can try this:
var accessFollowup;
try {
accessFollowup = !!user_access.followup.access;
} catch (e) {
accessFollowup = false;
}
You could also shorten by removing just the ternary by using !! to force last element into Boolean value:
var access_followup = !!user_access && !!user_access.followup && !!user_access.followup.access
very ugly code that works
var access_followup = (followup = (user_access || {}).followup) && followup.access;

Evaluate prompt value wont

I'm very new to JS - only a couple days in.
Trying to write a very basic prompt evaluated by an if statement.
When I run the code below, the user is prompted, but the statement is never evaluated by the if statement.
Any help? -- I realize the answer is probably simple and obvious, but as a SUPER beginner, what do I do?
var bool = prompt("What is an example of a boolean?");
if (typeof(bool) === "boolean") {
print("correct! that is a boolean");
print(bool) ;
};
In this case, assuming the user inputs something in the prompt, the type of the bool variable will always be a string. You'd rather check if the input compares to the string "true" or "false" etc., like this:
if (bool.toLowerCase() == "true" || bool.toLowerCase() == "false") {
...
}

Why is angular.isNumber() not working as expected?

It appears as if AngularJS's angular.isNumber is not working. It doesn't work with strings that are numbers. Am I doing something wrong? Should I just use isNaN()?
angular.isNumber('95.55') == false
angular.isNumber('95.55' * 1) == true
angular.isNumber('bla' * 1) == true
angular.isNumber(NaN) == true
I need something to see if a string is a number (when it actually is) and angular.isNumber() won't let me do that unless I multiply by 1, but if I do that then it will always be true. Also NaN is not a number (by definition) and so should return false.
In JavaScript, typeof NaN === 'number'.
If you need to recognise a String as a Number, cast it to Number, convert back to String and compare this against the input, for example.
function stringIsNumber(s) {
var x = +s; // made cast obvious for demonstration
return x.toString() === s;
}
stringIsNumber('95.55'); // true
stringIsNumber('foo'); // false
// still have
stringIsNumber('NaN'); // true
I was working on the same problem and I was trying to work around that edge case. So I created a slightly different approach.
FIDDLE
function isStringNumber(str) {
var parsed = parseFloat(str);
var casted = +str;
return parsed === casted && !isNaN(parsed) && !isNaN(casted);
}
Use it as below,
angular.isNumber(eval('99.55'))
for other expressions also we may use eval(input).
Note: eval() is a javascript method
Edit:
It is not recommended to use eval(), as document says Never use eval()!
Thanks #Diogo Kollross

Categories

Resources