|
1 | 1 | # Improved JavaScript Type Testing |
2 | | -A robust alternative to JavaScript's `typeof` keyword. |
3 | 2 |
|
4 | | -This is a JavaScript module that exports: [`is`](#is) (default) |
5 | | - |
6 | | ---- |
| 3 | +A robust alternative to JavaScript's built-in type testing. |
7 | 4 |
|
8 | 5 |
|
9 | | -## Get the type |
| 6 | +--- |
10 | 7 |
|
11 | | -### is() |
12 | 8 |
|
13 | | -The **is()** function determines the type of its argument and returns a [Type](#the-type-class) object. |
| 9 | +## Type Names |
| 10 | + |
| 11 | +This module uses an expanded set of type names that make no distinction between primitive values and objects. |
| 12 | +For example, `5` and `new String(5)` are both of type "number". |
| 13 | + |
| 14 | +| Type Name | Values |
| 15 | +| - | - |
| 16 | +| array | `Array` objects |
| 17 | +| bigint | _bigint_ primitives |
| 18 | +| boolean | `false`, `true`, `Boolean` objects |
| 19 | +| date | `Date` objects |
| 20 | +| error | `Error` objects |
| 21 | +| function | `Function` objects |
| 22 | +| map | `Map` objects |
| 23 | +| nan | `NaN` |
| 24 | +| null | `null` |
| 25 | +| number | _number_ primitives, `Number` objects; excludes `NaN` |
| 26 | +| object | instances of `Object` that don't match another type in this list |
| 27 | +| promise | `Promise` objects |
| 28 | +| regex | `RegExp` objects |
| 29 | +| set | `Set` objects |
| 30 | +| string | _string_ primitives, `String` objects |
| 31 | +| symbol | _symbol_ primitives |
| 32 | +| undefined | `undefined` |
| 33 | +| weakmap | `WeakMap` objects |
| 34 | +| weakset | `WeakSet` objects |
| 35 | + |
| 36 | +## Determine a Type |
| 37 | + |
| 38 | +The **is()** function returns an object describing the type of its argument. |
14 | 39 |
|
15 | 40 | Syntax: |
16 | | -> `is(value)` |
17 | | -
|
18 | | -Parameters: |
19 | | -- ***value*** - The value to determine the type of. |
20 | | - |
21 | | -Return value: |
22 | | -- A [Type](#the-type-class) object. |
23 | | - |
24 | | -### The Type class |
25 | | - |
26 | | -A String object storing a primitive type, with the following additional properties. |
| 41 | +> **is**(_value_) |
27 | 42 |
|
28 | | -| Property | Type | Description |
29 | | -| - | - | - |
30 | | -| .**type** | string | The type name returned by the `typeof` operator. |
31 | | -| .**objectType** | string | The object name used by `Object.prototype.toString()`. Undefined for primitive types. |
32 | | -| .**primitive** | string | True for primitive types. |
33 | | -| .**object** | string | True for object types. |
| 43 | +Returned object: |
| 44 | +| Property | Description |
| 45 | +| - | - |
| 46 | +| .**type** | The type name used by this module. |
| 47 | +| .**typeof** | The value returned by the `typeof` operator. |
| 48 | +| .**toStringTag** | The name used by `Object.prototype.toString()`. |
| 49 | +| .**constructorName** | The name of the argument's constructor, or `undefined`. |
| 50 | +| .**isObject** | True if the value is an object. |
| 51 | +| .**isPrimitive** | True if the value is a primitive. |
34 | 52 |
|
35 | | -### Example |
| 53 | +<details> |
| 54 | +<summary>Examples</summary> |
36 | 55 |
|
37 | 56 | ``` |
38 | | -is(2).type; // "number" |
39 | | -is(2).toString() // "number" |
40 | | -is(2) == "number"; //true |
41 | | -is(2).primitive; // true |
42 | | -is(2).object; // undefined |
43 | | -is(2).objectType; // undefined |
44 | | -
|
45 | | -let o = new Number(2); |
46 | | -is(o).type; // "number" |
47 | | -is(o).toString() // "number" |
48 | | -is(o) == "number"; //true |
49 | | -is(o).primitive; // undefined |
50 | | -is(o).object; // true |
51 | | -is(o).objectType; // "Number" |
| 57 | +let v; |
| 58 | +is(v).type // "undefined" |
| 59 | +is(v).typeof // "undefined" |
| 60 | +is(v).toStringTag // "Undefined" |
| 61 | +is(v).constructorName // undefined |
| 62 | +
|
| 63 | +v = null; |
| 64 | +is(v).type // "null" |
| 65 | +is(v).typeof // "object" |
| 66 | +is(v).toStringTag // "Null" |
| 67 | +is(v).constructorName // undefined |
| 68 | +
|
| 69 | +v = NaN; |
| 70 | +is(v).type // "nan" |
| 71 | +is(v).typeof // "number" |
| 72 | +is(v).toStringTag // "Number" |
| 73 | +is(v).constructorName // "Number" |
| 74 | +
|
| 75 | +v = 42; |
| 76 | +is(v).type // "number" |
| 77 | +is(v).typeof // "number" |
| 78 | +is(v).toStringTag // "Number" |
| 79 | +is(v).constructorName // "Number" |
| 80 | +
|
| 81 | +v = new Number(42); |
| 82 | +is(v).type // "number" |
| 83 | +is(v).typeof // "object" |
| 84 | +is(v).toStringTag // "Number" |
| 85 | +is(v).constructorName // "Number" |
| 86 | +
|
| 87 | +v = []; |
| 88 | +is(v).type // "array" |
| 89 | +is(v).typeof // "object" |
| 90 | +is(v).toStringTag // "Array" |
| 91 | +is(v).constructorName // "Array" |
| 92 | +
|
| 93 | +v = ()=>{}; |
| 94 | +is(v).type // "function" |
| 95 | +is(v).typeof // "function" |
| 96 | +is(v).toStringTag // "Function" |
| 97 | +is(v).constructorName // "Function" |
| 98 | +
|
| 99 | +class Foo {} |
| 100 | +v = new Foo(); |
| 101 | +is(v).type // "object" |
| 102 | +is(v).typeof // "object" |
| 103 | +is(v).toStringTag // "Object" |
| 104 | +is(v).constructorName // "Foo" |
| 105 | +
|
| 106 | +class Bar { |
| 107 | + get [Symbol.toStringTag](){ return "Foobar"; } |
| 108 | +} |
| 109 | +v = new Bar(); |
| 110 | +is(v).type // "object" |
| 111 | +is(v).typeof // "object" |
| 112 | +is(v).toStringTag // "Foobar" |
| 113 | +is(v).constructorName // "Bar" |
52 | 114 | ``` |
53 | 115 |
|
54 | | ---- |
55 | | - |
56 | | - |
57 | | -## Test for a type |
58 | | - |
59 | | -For each of the type-testing methods, the only parameter is the item to be tested. The return value is a boolean. |
| 116 | +</details> |
60 | 117 |
|
61 | | -**is.object()** |
62 | | -**is.primitive()** |
63 | 118 |
|
64 | | -**is.undefined()** |
65 | | -**is.null()** |
| 119 | +## Type Testing |
66 | 120 |
|
67 | | -**is.number()** - A real number. |
68 | | -**is.infinite()** \* |
69 | | -**is.nan()** \* |
| 121 | +Each of the type-testing methods return a boolean indicating if the argument is of that type. |
70 | 122 |
|
71 | | -\* Note that JavaScript doesn't correctly treat all undefined forms as `NaN`. For example, `1/0` and `0**0` are undefined forms, but JavaScript treats them as `Infinity`. |
72 | | - |
73 | | -**is.bigint()** |
74 | | -**is.boolean()** |
75 | | -**is.string()** |
76 | | -**is.symbol()** |
77 | | -**is.function()** |
78 | | - |
79 | | -**is.array()** |
80 | | -**is.date()** |
81 | | -**is.error()** |
82 | | -**is.regexp()** |
83 | | -**is.map()** |
84 | | -**is.set()** |
85 | | -**is.weakmap()** |
86 | | -**is.weakset()** |
87 | | -**is.promise()** |
| 123 | +Syntax: |
| 124 | +> is._typeTester_(_value_) |
| 125 | +
|
| 126 | +### Basics |
| 127 | + |
| 128 | +| Method | Tests for |
| 129 | +| - | - |
| 130 | +| is.**function**() | instance of `Function` |
| 131 | +| is.**object**() | instance of `Object` |
| 132 | +| is.**primitive**() | primitives |
| 133 | +| is.**null**() | `null` |
| 134 | +| is.**nullish**() | `undefined`, `null` |
| 135 | +| is.**undefined**() | `undefined` |
| 136 | +| is.**defined**() | not `undefined` |
| 137 | + |
| 138 | +### Booleans |
| 139 | + |
| 140 | +| Method | Tests for |
| 141 | +| - | - |
| 142 | +| is.**boolean**() | `false`, `true`, instance of `Boolean` |
| 143 | +| is.**falsy**() | `false`, `undefined`, `null`, `NaN`, `0`, `-0`, `0n`, `""`, [`document.all`](https://developer.mozilla.org/en-US/docs/Web/API/Document/all#conversion_to_boolean) |
| 144 | +| is.**truthy**() | not falsy |
| 145 | + |
| 146 | +### Numbers |
| 147 | + |
| 148 | +| Method | Tests for |
| 149 | +| - | - |
| 150 | +| is.**bigint**() | _bigint_ primitive |
| 151 | +| is.**date**() | instance of `Date` |
| 152 | +| is.**numberish**() | _number_ primitive, instance of `Number` |
| 153 | + |
| 154 | +_Numberish_ values can be more explicitly tested using the following methods: |
| 155 | + |
| 156 | +| Method | Tests for |
| 157 | +| - | - |
| 158 | +| is.**real**() | real numbers |
| 159 | +| is.**infinite**() | `Infinity`, `-Infinity` |
| 160 | +| is.**number**() | real numbers, `Infinity`, `-Infinity` |
| 161 | +| is.**nan**() | `NaN` |
| 162 | + |
| 163 | +Note that JavaScript doesn't always treat mathematical expressions of undefined or indeterminate form as you might expect. For example, `1/0` is an undefined form, but JavaScript evaluates it as `Infinity`. |
| 164 | + |
| 165 | +### Text |
| 166 | + |
| 167 | +| Method | Tests for |
| 168 | +| - | - |
| 169 | +| is.**regex**() | instance of `RegExp` |
| 170 | +| is.**string**() | _string_ primitive, instance of `String` |
| 171 | + |
| 172 | +### Collections |
| 173 | + |
| 174 | +| Method | Tests for |
| 175 | +| - | - |
| 176 | +| is.**array**() | instance of `Array` |
| 177 | +| is.**map**() | instance of `Map` |
| 178 | +| is.**set**() | instance of `Set` |
| 179 | +| is.**weakmap**() | instance of `WeakMap` |
| 180 | +| is.**weakset**() | instance of `WeakSet` |
| 181 | + |
| 182 | +### Other Common Types |
| 183 | + |
| 184 | +| Method | Tests for |
| 185 | +| - | - |
| 186 | +| is.**error**() | instance of `Error` |
| 187 | +| is.**promise**() | instance of `Promise` |
| 188 | +| is.**symbol**() | _symbol_ primitive |
| 189 | + |
| 190 | +## Additional Methods |
| 191 | + |
| 192 | +| Method | Description |
| 193 | +| - | - |
| 194 | +| is.**empty**(_value_) | Tests if an object's `.length` or `.size` property equals zero. |
| 195 | +| is.**of**(_value_, _class_) | Tests if _value_ is an instance of _class_. (Same as using the `instanceof` operator.) |
0 commit comments