Language: JavaScript
Defect: CompareTypeofToString (Category General 5)
Diagnose: The string result of the “typeof” operator is compared with something that is not a string, leading to a contradiction.
You can find this one in npm/cli. As usual, just got to deepcode.ai, open the repo and follow along. This one is an easy one...
Have a look at the picture below. It is a screenshot from the DeepCode dashboard.
As you can see DeepCode highlights the following code: typeof schema.minimum !== undefined
and explains
typeof is compared to undefined. This comparison is invalid, because typeof always returns strings.
It seems to be a very common mistake - especially for developers used to Java (see instanceof
in Java which does a type comparison). In JavaScript though, this will always be true
as the typeof operator results in a string (even if the string is equal to ' undefined'
) - see MDN on typeof.
JavaScript is a loosely typed language. That does not mean variables or properties do not have a specific type. Rather, the developer does not need to define the type explicitly and the type of a variable or property can be changed during execution. Also, JavaScript freely converts between types as long as possible and demanded by the context ( see MDN on Type conversion ). undefined
is a separate type in JavaScript with only value (you guess which one). null
is also a separate type (while calling typeof null
results in object
which is a bug in the language).
JavaScript comes with two types of equality operators: A strict equal (===
) and an abstract equal (==
) (see MDN on Comparison Operators ). There are corresponding unequal operators (!==
and !=
) . undefined
is strictly equal to itself and abstract equal to itself and null
. Comparing it to any other type (in our case a string) will result in false
. So, the above code will always result in true
. DeepCode and m, we guess the developer did not intend that.
But how should you do it now?
Well, using the above construct only in a correct fashion is possible and popular: typeof myVar == 'undefined'
which survives even if the variable was not declared before, and JavaScript runtimes commonly seem to optimize it. You thus expect a decent performance. Personally, I prefer typeof myVar == typeof unknown
because I think it is elegant and explains itself (also the IDE prevents misspelling).
Comparing to undefined
like myVar === undefined
has some caveats. First, if the variable was not declared, this will throw an exception. Secondly, it is possible to redefine undefine
in JavaScript and then you no longer compare apples with apples. Another option is to compare with void 0
(so myvar === void 0
) which generates an undefined
. You find this in some libraries.
Finally, let us have a look under the hood. For DeepCode, this is a type analysis. DeepCode knows that a call to typeof
results in a string
. It has a rule arguing that a comparison between undefined
and a different type such as a string is very very likely not what was intended. DeepCode has also seen this construct in other repos before and noticed that it has often been corrected there. It lists three occasions (the before and the after) in the selection called Example Fixes.
(Thanks to Nils Weller as proof reader :-) )
CU
0xff
Top comments (0)