Skip to content

Commit ef1ef23

Browse files
authored
Merge pull request #2 from wizard04wsu/dev
Dev
2 parents 356d7d0 + 7e18396 commit ef1ef23

File tree

5 files changed

+341
-191
lines changed

5 files changed

+341
-191
lines changed

README.md

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,93 @@
1-
# javascript-type-testing
2-
Improved JavaScript type testing
1+
# Improved JavaScript Type Testing
2+
A robust alternative to JavaScript's `typeof` keyword.
3+
4+
This is a JavaScript module that exports: [`is`](#is) (default)
5+
6+
---
7+
8+
9+
## Get the type
10+
11+
### is()
12+
13+
The **is()** function determines the type of its argument and returns a [Type](#the-type-class) object.
14+
15+
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+
The **Type** class extends the **String** class. In addition to storing a type name, its properties reveal whether the tested value was an object or a primitive.
27+
28+
Syntax:
29+
> `new Type(typeName, isPrimitive)`
30+
31+
Parameters:
32+
- ***typeName*** - (string)
33+
- ***objectType*** - (string) Optional. The object name used by `Object.prototype.toString()`. Pass this argument for object types only.
34+
35+
| Property | Type | Description |
36+
| --- | --- | --- |
37+
| .**type** | string | The type name. This is also the instance's primitive value. |
38+
| .**objectType** | string | The object name used by `Object.prototype.toString()`.. |
39+
| .**primitive** | string | If the `objectType` argument was falsy when constructed, this property was set to the type name. Otherwise, it's undefined. |
40+
| .**object** | string | If the `objectType` argument was truthy when constructed, this property was set to the type name. Otherwise, it's undefined. |
41+
42+
### Example
43+
44+
```
45+
is(2).type; // "number"
46+
is(2)+"" // "number"
47+
is(2) == "number"; //true
48+
is(2).primitive === "number"; // true
49+
is(2).object === "number"; // false
50+
is(2).objectType; // undefined
51+
52+
let o = new Number(2);
53+
is(o).type; // "number"
54+
is(o)+"" // "number"
55+
is(o) == "number"; //true
56+
is(o).primitive === "number"; // false
57+
is(o).object === "number"; // true
58+
is(o).objectType; // "Number"
59+
```
60+
61+
---
62+
63+
64+
## Test for a type
65+
66+
For each of the type-testing methods, the only parameter is the item to be tested. The return value is a boolean.
67+
68+
**is.object()**
69+
**is.primitive()**
70+
71+
**is.undefined()**
72+
**is.null()**
73+
74+
**is.number()**
75+
**is.number.real()** - This is most likely what you actually want to use when testing for a number.
76+
**is.number.infinite()**
77+
**is.number.NaN()** - Note that JavaScript doesn't correctly treat all undefined forms as `NaN` (e.g., `1/0` and `0**0`).
78+
79+
**is.bigint()**
80+
**is.boolean()**
81+
**is.string()**
82+
**is.symbol()**
83+
**is.function()**
84+
85+
**is.array()**
86+
**is.date()**
87+
**is.error()**
88+
**is.regexp()**
89+
**is.map()**
90+
**is.set()**
91+
**is.weakmap()**
92+
**is.weakset()**
93+
**is.promise()**

isType.js

Lines changed: 0 additions & 189 deletions
This file was deleted.

isType.mjs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
2+
class Type extends String {
3+
/**
4+
* @constructor
5+
* @param {string} typeName - The type's name, regardless of whether it's an object or a primitive.
6+
* @param {string} [objectType] - If this is an object, the object's name. Falsy for a primitive.
7+
*/
8+
constructor(typeName, objectType){
9+
if(!(typeof typeName === "string" || typeName instanceof String))
10+
throw new TypeError("'typeName' must be a string");
11+
typeName = String(typeName);
12+
if(objectType){
13+
if(!(typeof objectType === "string" || objectType instanceof String))
14+
throw new TypeError("'objectType' must be a string");
15+
objectType = String(objectType);
16+
}
17+
18+
super(typeName);
19+
20+
if(objectType){
21+
this.type = this.object = typeName;
22+
this.objectType = objectType;
23+
}
24+
else{
25+
this.type = this.primitive = typeName;
26+
}
27+
}
28+
}
29+
30+
function getToStringTag(obj){
31+
return Object.prototype.toString.call(obj).slice(8, -1);
32+
}
33+
34+
function is(value){
35+
if(value === void 0)
36+
return new Type("undefined");
37+
if(value === null)
38+
return new Type("null");
39+
const type = typeof value;
40+
if(type === "function")
41+
return new Type("function", "Function");
42+
if(type === "object"){
43+
const toStringTag = getToStringTag(value);
44+
for(const objectType of ["Boolean","Number","String"]){
45+
if(value instanceof globalThis[objectType])
46+
return new Type(objectType.toLowerCase(), toStringTag);
47+
}
48+
return new Type(type, toStringTag);
49+
}
50+
return new Type(type);
51+
}
52+
53+
54+
is.object = (v)=>(v instanceof Object);
55+
is.primitive = (v)=>!is.object(v);
56+
57+
const typeofTypes = [
58+
/*** primitives ***/
59+
"undefined",
60+
"null",
61+
"bigint",
62+
"symbol",
63+
64+
/*** primitives & objects ***/
65+
"boolean",
66+
"number",
67+
"string",
68+
69+
/*** objects ***/
70+
//"object",
71+
"function",
72+
];
73+
for(const type of typeofTypes){
74+
is[type] = (v)=>(is(v).type === type);
75+
}
76+
77+
is.number.real = (v)=>(is.number(v) && Number.isFinite(1*v));
78+
is.number.infinite = (v)=>(is.number(v) && !Number.isFinite(1*v) && !Number.isNaN(1*v));
79+
is.number.NaN = (v)=>(is.number(v) && Number.isNaN(1*v)); //Note that JavaScript doesn't correctly treat all undefined forms as NaN (e.g., 1/0 and 0**0).
80+
81+
const otherCommonTypes = [
82+
"Error",
83+
"Date",
84+
"RegExp",
85+
"Array",
86+
"Map",
87+
"Set",
88+
"WeakMap",
89+
"WeakSet",
90+
"Promise",
91+
];
92+
for(const objectType of otherCommonTypes){
93+
is[objectType.toLowerCase()] = (v)=>(v instanceof globalThis[objectType]);
94+
}
95+
96+
97+
98+
export { is as default };

test/test.htm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<html><head><title>isType test</title><script src="test.js" type="module"></script></head><body>
2+
3+
View the console.
4+
5+
</body></html>

0 commit comments

Comments
 (0)