Native sugar methods to standardise value checking in JavaScript.
JavaScript has some very unintuitive ways to check types and values.
ìnstanceof
works great to check the type of an object
const date = new Date()
date instanceof Date // true
It fails when using an iFrame as described [here] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray). Therefore an extra method Array.isArray
was implemented.
And what about checking primitives who are not an instance?
as explored in this article, typeof
can behave unexpected for certain values.
Who would have thought that NaN
, an acronym for Not A Number, returns
typeof NaN // "number"
This unintuitive behavior was noticed and since NaN !== NaN // true
(?!?) is as unexpected as it gets a method was implemented:
Number.isNaN(NaN) // true (window.isNaN also exists)
Over the years additional classes were extended to make type and value checking easier but also behaves inconsistent:
Only evaluates primitive
Number.isInteger(1) // true
Number.isInteger(new Number(1)) // false
evaluates primitive and object
Number.isNaN(NaN) // true
Number.isNaN(new Number(NaN)) // true
Array.isArray([]) // true
Array.isArray(new Array()) // true
Some classes do not have the accoring and expected methods at all:
Boolean.isBoolean(true) // TypeError: Boolean.isBoolean is not a function.
String.isString("foo") // TypeError: String.isString is not a function.
Number.isFloat(1) // TypeError: Number.isFloat is not a function.
instanceof
andtypeof
are useful but not always intuitive. Alsoinstanceof
is not always reliable.- Javascript has implemented methods to help value check but their behavior is inconsistent
- Some useful and expected methods are missing completely.
- Extended core type classes with static methods according to the table below.
- Make their behavior consistent
Method | Description | Implemented | Behavior |
---|---|---|---|
Boolean.isBoolean | checks if value is a boolean primitive or a Boolean instance |
Boolean.isBoolean = value => Object.prototype.toString.call(value) === "[object Boolean]" |
|
Number.isNumber | checks if value is an number primitive or a Number instance |
Number.isNumber = value => Object.prototype.toString.call(value) === "[object Number]" && !Number.isNaN(value) && isFinite(value) |
|
Number.isInteger | checks if value is an integer | (:heavy_check_mark:)* | |
Number.isFloat | checks if value is a float | Number.isFloat = value => Number.isNumber(value) && !Number.isInteger(value) * |
|
Number.isNaN | checks if value is NaN |
✔️ | |
Number.isFinite | checks if value is finite | ✔️ | |
String.isString | checks if value is a string primitive or a String instance |
String.isString = value => Object.prototype.toString.call(value) === "[object String]" |
|
Object.isObject | checks if value is an Object instance |
Object.isObject = value => Object.prototype.toString.call(value) === "[object Object]" |
|
Symbol.isSymbol | checks if value is a Symbol |
Symbol.isSymbol = value => Object.prototype.toString.call(value) === "[object Symbol]" |
|
Array.isArray | checks if value is an Array instance |
✔️ |
*extend so Number
instances are treated as follows:
Number.isInteger(new Number(1)) // true