DeepCode’s Top Findings#6: JavaScript Result of Typeof not compared with String

Frank Fischer
DeepCodeAI
Published in
3 min readJan 16, 2020

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 one possible value (you guess which one). null is also a separate type (although typeof null results in 'object' , which is actually 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 me, we guess the developer did not intend that.

But how should you do it now?

Well, using the above construct 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 , which generates undefined (so myvar === void 0). 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 betweenundefined 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

--

--