In Javascript, almost all expressions (all expressions?) have a "truthiness" value. If you put an expression in a statement that expects a boolean, it will evaluate to a boolean equivalent. For example:
let a = 'foo'
if (a) {
console.log('a is truthy!');
}
// Will print 'a is truthy!'.
In some workplaces it is common to coerce an expression in this situation into an actual boolean by negating it twice:
let a = 'foo'
if (!!a) {
console.log('a is truthy!');
}
// Will print 'a is truthy!'.
My question: Is this merely a matter of style? Is it purely to communicate to someone reading the code that we really recognize that a
is not a boolean, but that we intend to evaluate it as such anyway? Or do there exist any expressions or values of a
where if (a)
actually evaluates to a different boolean value than if (!!a)
?
The null in TypeScript is a special value & also a data type. The value null represents the intentional absence of any object value. It is one of TypeScript's primitive values and is treated as falsy for boolean operations. The value of null is represented in using the literal null .
Truthy - Typescript. Typescript. Truthy. JavaScript has a concept of truthy i.e. things that evaluate like true would in certain positions (e.g. if conditions and the boolean && || operators).
(this as any ) is just a Type Assertion that works on dev/compiling time and has no side effects on run time because it is purely a Typescript thing.
Logical AND (&&) Relational expressions always evaluate to true or false , so when used like this, the && operator itself returns true or false . Relational operators have higher precedence than && (and || ), so expressions like these can safely be written without parentheses.
Is this merely a matter of style? Is it purely to communicate to someone reading the code that we really recognize that a is not a boolean, but that we intend to evaluate it as such anyway?
See Why use if (!!err)?
Or do there exist any expressions or values of a where
if (a)
actually evaluates to a different boolean value thanif (!!a)
?
No, as long as a
always refers to the same thing (for example, it is not a getter that returns random content). See the specification:
Logical NOT Operator (!
)
- Let expr be the result of evaluating UnaryExpression.
- Let oldValue be ToBoolean(? GetValue(expr)).
- If oldValue is true, return false.
- Return true.
The if
statement
- Let exprRef be the result of evaluating Expression.
- Let exprValue be ToBoolean(? GetValue(exprRef)).
- If exprValue is true, then
- Let stmtCompletion be the result of evaluating the first Statement.
- Else,
- Let stmtCompletion be the result of evaluating the second Statement.
- Return Completion(UpdateEmpty(stmtCompletion, undefined)).
Both, the logical NOT operator and the if
statement call the ToBoolean
function. As a result, there is no way that if (a)
and if (!!a)
are different (still assuming both a
s refer the same thing).
The truthyness of a
and !!a
will always be the same.
ToBoolean is just a static lookup, and does not execute any user defined code at any step. Using !
applies ToBoolean, and negates the result. if
also applies ToBoolean, and takes the result. Both don't really do much more. As double negation is the identity, and ToBoolean doesn't change anything if the input is already boolean, they will always be the same.
TL;DR; in pseudocode, "ToBoolean(a) === ToBoolean(booleanNot(ToBoolean(booleanNot(ToBoolean(a)))))".
Note that it is possible to mutate the variable on each lookup, and produce tests that may be confusing, but don't actually disprove the above. a
is simply changed after the first evaluation - whether !!
was used or not, makes no difference:
let x = 0;
let objectEnvironment = { get a() { return x++; } };
with(objectEnvironment){
if (a) console.log("truthy?");
if (!!a) console.log("double negated truthy?");
}
If you swap the use of a
and !!a
in above example, the output won't change. Note that with
is an error in strict mode already, and should not be used. It only served to show that GetValue can be used to execute user-defined code. However, it's undetectable, whether logical not was used or not, so making a condition for it should not work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With