Skip to content

Commit 3ef9904

Browse files
committed
- rewrite Type class, update is() accordingly
- add types to test - update README - update test cases
1 parent dc241b0 commit 3ef9904

File tree

3 files changed

+231
-134
lines changed

3 files changed

+231
-134
lines changed

README.md

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,29 +30,32 @@ Syntax:
3030
3131
Parameters:
3232
- ***typeName*** - (string)
33-
- ***isPrimitive*** - (boolean) Optional.
33+
- ***objectType*** - (string) Optional. The object name used by `Object.prototype.toString()`. Pass this argument for object types only.
3434

3535
| Property | Type | Description |
3636
| --- | --- | --- |
37-
| .**type** | string | The type name. This is equivalent to the class's string value. |
38-
| .**primitive** | string | If the `isPrimitive` argument was truthy when constructed, this property was set to the type name. Otherwise, it's undefined. |
39-
| .**object** | string | If the `isPrimitive` argument was falsy when constructed, this property was set to the type name. Otherwise, it's undefined. |
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. |
4041

4142
### Example
4243

4344
```
44-
let u;
45-
let p = 2;
46-
let o = new Number(3);
47-
48-
is(u).type; // "undefined"
49-
is(p).type; // "number"
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);
5053
is(o).type; // "number"
5154
is(o)+"" // "number"
52-
5355
is(o) == "number"; //true
5456
is(o).primitive === "number"; // false
5557
is(o).object === "number"; // true
58+
is(o).objectType; // "Number"
5659
```
5760

5861
---
@@ -62,8 +65,8 @@ is(o).object === "number"; // true
6265

6366
For each of the type-testing methods, the only parameter is the item to be tested. The return value is a boolean.
6467

65-
**is.primitive()**
6668
**is.object()**
69+
**is.primitive()**
6770

6871
**is.undefined()**
6972
**is.null()**
@@ -77,9 +80,14 @@ For each of the type-testing methods, the only parameter is the item to be teste
7780
**is.boolean()**
7881
**is.string()**
7982
**is.symbol()**
83+
**is.function()**
84+
8085
**is.array()**
8186
**is.date()**
87+
**is.error()**
8288
**is.regexp()**
83-
**is.function()**
84-
85-
89+
**is.map()**
90+
**is.set()**
91+
**is.weakmap()**
92+
**is.weakset()**
93+
**is.promise()**

isType.mjs

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,98 @@
11

2-
const basicTypes = [
3-
"undefined",
4-
"null",
5-
"number",
6-
"bigint",
7-
"boolean",
8-
"string",
9-
"symbol",
10-
"array",
11-
"date",
12-
"regexp",
13-
"function",
14-
];
15-
162
class Type extends String {
173
/**
184
* @constructor
195
* @param {string} typeName - The type's name, regardless of whether it's an object or a primitive.
20-
* @param {boolean} [isPrimitive] - Is this a primitive value?
6+
* @param {string} [objectType] - If this is an object, the object's name. Falsy for a primitive.
217
*/
22-
constructor(typeName, isPrimitive){
23-
typeName = String(typename);
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+
2418
super(typeName);
25-
this.type = this[ isPrimitive ? "primitive" : "object" ] = 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+
}
2627
}
2728
}
2829

30+
function getToStringTag(obj){
31+
return Object.prototype.toString.call(obj).slice(8, -1);
32+
}
33+
2934
function is(value){
3035
if(value === void 0)
31-
return new Type("undefined", true);
36+
return new Type("undefined");
3237
if(value === null)
33-
return new Type("null", true);
38+
return new Type("null");
3439
const type = typeof value;
3540
if(type === "function")
36-
return new Type("function", false);
41+
return new Type("function", "Function");
3742
if(type === "object"){
38-
const deepType = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
39-
if(deepType.match(new RegExp(`^${basicTypes.join("|")}$`, "ui")))
40-
return new Type(deepType, false);
41-
return new Type(type, false);
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);
4249
}
43-
return new Type(type, true);
50+
return new Type(type);
4451
}
4552

46-
function fn(type){
47-
return (v)=>(is(v).type === type);
48-
}
4953

50-
is.primitive = (v)=>(is(v).primitive !== void 0);
51-
is.object = (v)=>(is(v).object !== void 0);
54+
is.object = (v)=>(v instanceof Object);
55+
is.primitive = (v)=>!is.object(v);
5256

53-
for(const type of basicTypes){
54-
is[type] = fn(type);
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);
5575
}
5676

5777
is.number.real = (v)=>(is.number(v) && Number.isFinite(1*v));
5878
is.number.infinite = (v)=>(is.number(v) && !Number.isFinite(1*v) && !Number.isNaN(1*v));
5979
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).
6080

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+
6196

6297

6398
export { is as default };

0 commit comments

Comments
 (0)