
As the name implies, the typeof keyword is used to determine the types of data. This is one of the most common JS keywords found in JS apps. Knowing the type of data you are working on is often found crucial. In this post, we will look into the typeof keyword in JS.
typeof usage
typeof data
The data is the variable we want to get the data type. Notice there is no parenthesis just the typeof keyword followed by a space and the data.
Let’s see other examples:
What it returns
typeof keyword returns one of the following data types:
- string
- number
- undefined
- object
- function
- boolean
- symbol
- bigint
string: Anything between “” is a string in JS:
let str = "str"
The variable str is a string data type. So typeof str will return string.
number: This represents numbers 0~9. typeof against a Number type will return “number”.
let num = 90l(typeof num)
Output:
$ node typeofnumber
The NaN also returns number contrary to its meaning NaN => Not a Number
let nan = NaNl(typeof nan)
Output:
$ node typeofnumber
This is very confusing, how can a value that is “Not a Number” eval to a number? To check for NaN, it’s obvious we can’t use the typeof keyword, we will use the isNaN function.
let nan = NaNl(typeof nan)l(isNaN(nan))
Output:
numbertrue
let undefl(undef)let undef1 = undefinedl(undef1)
undefined This is returned when a variable has no value set yet or has an undefined set explicitly.
When typeof is set against an undefined variable it will return “undefined”:
let undefl(under)let undef1 = undefinedl(undef1)l(typeof undef)l(typeof undef1)
Output:
$ node typeofundefinedundefined
This is good, so we can check for undefined values using the typeof keyword.
object: This is a bit tricky. Many variable types return objects.
null, array, object
let nul = nulllet obj = { d: 90 }let arr = [90]l(typeof nul)l(typeof obj)l(typeof arr)
Output:
$ node typeofobjectobjectobject
We can see that all of them return the object as type. With this, we cannot test null and array with the typeof operator.
But, null being an object. That’s mind-boggling. History told us this was an unfixed bug in Js and it has haunted us p to this day. Fixing the bug now, we crash billions of JS codebase and apps. So we have to live with it.
To check for null, we will use either the loose equality or strict equality, in both, the == resolves to true to itself:
let nul = nulll(nul == null)l(nul === null)
Output:
truetrue
function: functions resolve to “function” under typeof. Pretty easy. regular functions, expression or arrow functions, and IIFEs all resolve to “function”.
function func() {}const arrFunc = () => {}l(typeof func)l(typeof arrFunc)
Output:
$ node typeoffunctionfunction
boolean: Boolean has two values true or false. These return the boolean type.
let bool = true(bool)
Output:
$ node typeofboolean
So we see its quite easy to check for booleans. Boolean shave truthy and falsy values. All values in JS are truthy except the falsy ones. falsy values are:
- 0
- “” (Empty string)
- NaN
- false
- null
- undefined
symbol: This is used to creating non-clashing names in JS. They are mostly used in creating keys in objects. These return “symbol” string.
let sym = Symbol("sym")l(typeof sym)
Output:
$ node typeofsymbol
bigint
BigInt is a built-in object that represents numbers between range 2⁵³ — 1. To create a bigint variable type, we append n to the end of an integer literal. bigint is returned when a variable of BigInt is used against typeof:
let bigint = 90nl(typeof bigint)
Output:
$ node typeofbigint
typeof and wrapper functions
Using new Boolean, new String, etc breaks the typeof result on them.
If I do this:
let bool = new Boolean(true)
It will no longer return true, it will return an object when its type is checked with typeof
let bool = new Boolean(true)l(typeof bool)
Output:
$ node typeofobject
These wrapper functions break the data type. Whenever we use wrapper functions on primitives, JS coerces them to objects. We know primitive types do not have properties, they are standalone.
let str = "str"let num = 90
But if we do this to str:
str.length
We are accessing a property in the primitive, it shouldn’t be so but yet we have a result:
3
JS coerces str primitive to object then have the length property retrieved. On returning the result the str becomes primitive again.
In str.length property, JS did this:
l(new String("str").length)
It wrapped the str in new String() before accessing the length property.
typeof and objects
As we saw above Arrays, null, object, NaN all return “object”. Others concepts, RegExp, Date all return “object”. So we cannot test for Array or any of them using typeof.
Array has Array#isArray(...) that correctly determines a data is an Array.
To check for null you can either
isNull === null
or
!isNull && typeof isNull == "object"
For NaN use isNaN or Number#isNaN API.
For Date, use duck typing:
typeof date.getMonth === "function"
or you can use instanceof but it will return for invalid dates too.
Conclusion
typeof is both a powerful and indeterminate tool in type checking. It kind of has a buggy behavior when dealing with null, NaN, object, Array, Object, etc types. However, it is useful for some primitive types: number, bigint, symbol, undefined, string, boolean.
If you have any questions regarding this or anything I should add, correct or remove, feel free to comment, email or DM me.
Thanks!