I understand this may be a classical javascript issue, but I too often found myself using :
if (!something) {
//...
}
to validate that this something
is not undefined
or null
, in TypeScript.
This is very error-prone! When used on a number
"0" will match, and when used on an enum
the first item will match too (by default, the first item has a value of "0")!
Is there a way to deal with this in TypeScript? Is there a way to configure TypeScript to disallow an exclamation mark in front of anything except a boolean
(and any
)? Would this configuration make sense or am I missing something trivial?
Should :
if (something === null || something === undefined) {
//...
}
be used instead, to validate that something is defined or not? And is there a way to enforce this in a team?
You can use the strict-boolean-expressions TSLint rule to disallow this sort of thing.
You can see some examples of the rule here, but this is an excerpt that's particularly relevant to your question. Places where the rule would find errors are marked with ~~~
and the error message is written next to that marking:
/*** PrefixUnary Expressions ***/
/*** Invalid ***/
!!numType;
~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is a number. Only booleans are allowed.]
!strType;
~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is a string. Only booleans are allowed.]
!objType;
~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is always truthy. Only booleans are allowed.]
!enumType;
~~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is an enum. Only booleans are allowed.]
!!classType;
~~~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is always truthy. Only booleans are allowed.]
!bwrapType;
~~~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is always truthy. Only booleans are allowed.]
!!undefined;
~~~~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is always truthy. Only booleans are allowed.]
~~~~~~~~~ [This type is not allowed in the operand for the '!' operator because it is always falsy. Only booleans are allowed.]
/*** Valid ***/
!!boolFn();
!boolExpr;
!!boolType;
/*** If Statement ***/
/*** Invalid ***/
if (numType) { /* statements */ }
~~~~~~~ [This type is not allowed in the 'if' condition because it is a number. Only booleans are allowed.]
if (objType) { /* statements */ }
~~~~~~~ [This type is not allowed in the 'if' condition because it is always truthy. Only booleans are allowed.]
if (strType) { /* statements */ }
~~~~~~~ [This type is not allowed in the 'if' condition because it is a string. Only booleans are allowed.]
if (bwrapType) { /* statements */ }
~~~~~~~~~ [This type is not allowed in the 'if' condition because it is always truthy. Only booleans are allowed.]
if (strFn()) { /* statements */ }
~~~~~~~ [This type is not allowed in the 'if' condition because it is a string. Only booleans are allowed.]
if (MyEnum.A) { /* statements */ }
~~~~~~~~ [This type is not allowed in the 'if' condition because it is an enum. Only booleans are allowed.]
if (classType) { /* statements */ }
~~~~~~~~~ [This type is not allowed in the 'if' condition because it is always truthy. Only booleans are allowed.]
To answer your other side question briefly, the below code snipped is a nice way to check if something is defined or not:
if (something == null) {
// will enter here if `something === null || something === undefined`
}
See here for more details on the above
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