loading...
Cover image for DeepCode’s Top Findings#6: JavaScript Result of Typeof not compared with String
DeepCode.AI

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

cu_0xff profile image cu_0xff 🇪🇺 Originally published at Medium ・3 min read

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.
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.

Example Fixes

(Thanks to Nils Weller as proof reader :-) )

CU

0xff

Posted on by:

cu_0xff profile

cu_0xff 🇪🇺

@cu_0xff

Veteran in IT, Xoogler, Ex-Microsoft, works in Static Program Analysis

DeepCode.AI

DeepCode learns from GitHub project data to give developers AI-powered code reviews

Discussion

markdown guide