Javascript types and type checking
Tags: javascript, types, beginners
Published: 2020-02-12 21:35:11

---
title: Javascript types and type checking
published: true
description: Types overview and planning for quirks in the JavaScript language
tags: javascript, types, beginner
---

[//]: # (Deep Javascript Foundations Notes from getify on Frontend Masters)


####Types

Note: throughout this post, I shorten JavaScript to 'JS'. 

The reason for the idea that "everything is an object" in JS is because most of the values in JS can *behave* as objects. But this doesn't make them objects. 

JS Types that differ from objects are Primitive Types:
- undefined
- null
- string (the string literal, created "with quotes like this")
- number
- boolean (these are actual special values `true` and `false`, not 0 and 1 like some other languages)
- symbol (added with ES6)
- bigint (added in ES10, 2019) 

Other things that behave like types that are not explicitly listed as types in the spec:
- undeclared
- null (quirky, due to a historical bug)
- function (referred to as a subtype of the object type, a "callable object")
- array (a subtype of the object type, even though it has specific behavior)

The only items in JS that are actual objects are:
- object
- function
- array

####Variables, types, and `typeof`
Unlike in other languages where the type is declared when creating the variable, such as in C, `int myNum = 3;`, In JS, variables don't have types, but the values contained in the variable do, so this is how they are evaluated, and can change over time depending on what they are assigned to. 
```javascript
var v;
typeof v;   // "undefined"

v = "1";
typeof v;   // "string"

v = 2;
typeof v;   // "number"

v = true;
typeof v;   // "boolean"

v = {};
typeof v;   // "object"

v = Symbol;
typeof v;   // "symbol"
```

The typeof operator will *always* return a string, and there is a short list of values it can be returned (essentially an enum list). So, when checking for type,  always make sure to put quotes around the value you are checking for, or the expression will not evaluate as expected.
```javascript
let v = undefined;

typeof v === "undefined";  // true

typeof v === undefined;  // will return false
```

Note that there is some "quirky" behavior when using `typeof`. 
```javascript
typeof doesntExist;   // "undefined"

var v = null;   // "object"

v = function() {}; 
typeof v;   // "function"

v = [1, 2, 3];
typeof v;   // "object"

v = 42n;
// or: BigInt(42)
typeof v;   // "bigint"
```
Note that `null` will return the "object" type, so it can fail checks. This can basically be treated as a bug in the language (but there are historical reasons for it). For this reason, if you want to assign a variable to an "empty" value, it's best to avoid using `null`. Either leave it blank or assign it to `undefined` if you want to be more explicit. The same goes for assigning `0` as a 'placeholder' value to a variable, since zero is a number, and the variable will evaluate to that type and can cause unplanned-for behavior.
 
Note also that when checking a variable that didn't exist (above), it still returned "undefined". There is no "undeclared" type in JS, so you could get undefined back from a check even if the variable has never been declared, but you can *also* get "undefined" back when the variable *has* been declared but not yet assigned a value. The `typeof` operator is the only operator in JS that is able to reference a thing that does not exist and not throw an error.

```javascript
if (typeof DoesntExist) {
  console.log("passed the if check");
}
// evaluates to true, logs "passed the if check"

if (DoesntExist) { 
  console.log("passed");
} 
// this will throw an error

// even more explicit
if (typeof DoesntExist !== "undefined") {
  console.log("this will only return if the variable exists and something has been assigned to it");
}
```
The full list of what `typeof` can return is: 

|Type |	Result|
|:----|:----|
|Undefined|	"undefined"|
|Null|	"object" |
|Boolean|	"boolean"|
|Number|	"number"|
|BigInt (new in ECMAScript 2020)|	"bigint"|
|String|	"string"|
|Symbol (new in ECMAScript 2015)|	"symbol"|
|Function object (implements [[Call]] in ECMA-262 terms)|	"function"|
|Any other object|	"object"|


####Special Values: NaN
A good mental model to use for NaN is "invalid number" as opposed to the instinctual "Not a Number". 
NaN is returned if, for example, you try to convert an invalid string into a number, or if JS tries to do so through implicit conversion. 
```javascript

var x = Number("n/a");  // NaN
var y = Number("39") // 39  here JS does implicit conversion
y - x; // NaN   because JS implicitly tries to convert x to a number

x === x  // false 
```

NaN is the only value in JS that is not equal to itself, which is how the `x === x` comparison can fail. 

JS does ship with a way to check for the NaN value, `isNaN()`, but this too can have some quirks. The reason is because it first tries to coerce the value passed in to a number, which can result in false positives.
```javascript
isNaN("a string");   // true
```
Above, it is coercing the string to a number, which results in the NaN value, so it returns true (the same way declaring `x` in the block above it did). 
As a result of this unexpected behavior, ES6 shipped with a new utility `Number.isNaN()`, which will *not* try to coerce the parameter to a number first.
```javascript
Number.isNaN("a string");   // false
```

####Special Values: Negative zero `-0`

The negative zero can have some unexpected consequences. When using the -0, be aware of some of the gotchas when using comparison operators, demonstrated below. 

```javascript
let trendRate = -0;
trendRate === -0;  // true

trendRate === 0;  // true 
trendRate < 0;   // false
trendRate > 0;   // false

// since the triple equals doesn't reliably return comparisons to zero, 
// the Object.is() method was introduced, which can reliably check for -0
Object.is(trendRate, -0);  // true
Object.is(trendRate, 0);  // false

trendRate.toString();  // "0"  the sign is dropped when converted to a string

```
The takeaway from the above is that, if you need to check for a negative zero, use the `Object.is()` method, and if you need it in string form, don't use the `toString()` method. One option would be to create your own function that will check the parameter using the `Object.is()` method, and then create and return a string literal `"-0"`.
```javascript
function negZeroToString(input) { 
  if (Object.is(input, -0)) {
    return "-0";
  } else {
    return new Error (`${input} is not the number negative zero! This function only accepts negative zero as an argument.`);
  }
}
```

And that's a brief overview. Hopefully you like this 'type of' post (womp womp)!