Skip to content

Commit 7417964

Browse files
committed
rewrite; test and docs WIP
1 parent efa2a23 commit 7417964

File tree

1 file changed

+77
-142
lines changed

1 file changed

+77
-142
lines changed

isType.mjs.js

Lines changed: 77 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,164 +1,99 @@
11
/** @module isType */
22

3-
// Type names and the class each refers to.
4-
const OBJECT_TYPES = {
5-
array: Array,
6-
boolean: Boolean,
7-
date: Date,
8-
error: Error,
9-
function: Function,
10-
map: Map,
11-
number: Number,
12-
promise: Promise,
13-
regex: RegExp,
14-
set: Set,
15-
string: String,
16-
weakmap: WeakMap,
17-
weakset: WeakSet,
3+
const TYPES = {
4+
array: { class: Array },
5+
bigint: { primitive: "bigint" },
6+
boolean: { primitive: "boolean", class: Boolean },
7+
date: { class: Date },
8+
error: { class: Error },
9+
function: { class: Function },
10+
map: { class: Map },
11+
nan: {},
12+
null: {},
13+
number: {},
14+
numberish: { primitive: "number", class: Number },
15+
object: {},
16+
promise: { class: Promise },
17+
regex: { class: RegExp },
18+
set: { class: Set },
19+
string: { primitive: "string", class: String },
20+
symbol: { primitive: "symbol", },
21+
undefined: { primitive: "undefined", },
22+
weakmap: { class: WeakMap },
23+
weakset: { class: WeakSet },
1824
};
1925

20-
// Initial type names.
21-
const TYPE_NAMES = [
22-
"array",
23-
"bigint",
24-
"boolean",
25-
"date",
26-
"error",
27-
"function",
28-
"map",
29-
"nan",
30-
"null",
31-
"number",
32-
"object",
33-
"promise",
34-
"regex",
35-
"set",
36-
"string",
37-
"symbol",
38-
"undefined",
39-
"weakmap",
40-
"weakset",
41-
];
42-
43-
4426
/**
45-
* Descriptors of a value's type.
46-
* @class Type
27+
* A collection of boolean properties indicating the type of the given value.
28+
* @class TypeTest
4729
* @extends {String}
4830
*/
49-
class Type extends String {
50-
51-
#name;
52-
#typeofType;
53-
#toStringTag;
54-
#constructorName;
55-
#isPrimitive;
31+
class TypeTest extends String {
5632

5733
/**
5834
* @constructor
59-
* @param {string} name - Custom type name.
60-
* @param {string} typeofType - The value returned by the `typeof` operator.
61-
* @param {string} [toStringTag] - For objects. The name used by `Object.prototype.toString.call()`.
62-
* @param {string} [constructorName] - For objects. The name of the argument's constructor.
35+
* @param {*} value - The value to be tested.
6336
*/
64-
constructor(name, typeofType, toStringTag, constructorName){
37+
constructor(value){
6538

66-
super(name);
67-
this.#name = name;
39+
let typeName;
6840

69-
this.#typeofType = typeofType;
70-
this.#toStringTag = toStringTag;
71-
this.#constructorName = constructorName;
41+
if(value === null){
42+
typeName = "null";
43+
}
44+
else{
45+
typeName = "object";
46+
47+
for(const name in TYPES){
48+
const type = TYPES[name];
49+
if(typeof value === type.primitive || (type.class && value instanceof type.class)){
50+
typeName = name;
51+
break;
52+
}
53+
}
54+
}
7255

73-
this.#isPrimitive = constructorName === void 0;
74-
}
75-
76-
/** @member {string} */
77-
get type(){ return this.#name; }
78-
79-
/** @member {string} */
80-
get ["typeof"](){ return this.#typeofType; }
81-
82-
/** @member {string} */
83-
get toStringTag(){ return this.#toStringTag; }
84-
85-
/** @member {string} */
86-
get constructorName(){ return this.#constructorName; }
87-
88-
/** @member {boolean} */
89-
get isPrimitive(){ return this.#isPrimitive; }
90-
91-
/** @member {boolean} */
92-
get isObject(){ return !this.#isPrimitive; }
93-
}
94-
95-
96-
97-
/**
98-
* Determine the type of a value.
99-
* @param {*} value
100-
* @returns {Type}
101-
*/
102-
function is(value){
103-
104-
let typeName,
105-
typeofType = typeof value,
106-
toStringTag,
107-
constructorName;
108-
109-
if(value instanceof Object){
110-
toStringTag = Object.prototype.toString.call(value).slice(8, -1);
111-
constructorName = value.constructor.name || "";
112-
}
113-
114-
if(value === null)
115-
typeName = "null";
116-
else if(Number.isNaN(value) || (value instanceof Number && Number.isNaN(value.valueOf())))
117-
typeName = "nan";
118-
else if(!["object", "function"].includes(typeofType))
119-
typeName = typeofType;
120-
else{
121-
typeName = "object";
122-
for(const name in OBJECT_TYPES){
123-
if(value instanceof OBJECT_TYPES[name]){
124-
typeName = name;
125-
break;
56+
if(typeName === "numberish"){
57+
if(Number.isNaN(value) || (value instanceof Number && Number.isNaN(value.valueOf()))){
58+
typeName = "nan";
59+
}
60+
else{
61+
typeName = "number";
12662
}
12763
}
64+
65+
super(typeName);
66+
67+
for(const name in TYPES){
68+
this[name] = typeName === name;
69+
}
70+
71+
this.numberish = this.number || this.nan;
72+
if(this.number){
73+
this.real = Number.isFinite(this.object ? value.valueOf() : value);
74+
this.infinite = !this.real;
75+
}
76+
77+
this.primitive = !this.object;
78+
this.objectish = this.object || this.null;
79+
80+
this.defined = !this.undefined;
81+
this.nullish = this.undefined || this.null;
82+
83+
this.falsy = !value;
84+
this.truthy = !this.falsy;
85+
86+
if(this.string || this.array){
87+
this.empty = value.length === 0;
88+
}
89+
else if(this.map || this.set || this.weakmap || this.weakset){
90+
this.empty = value.size === 0;
91+
}
12892
}
129-
130-
return new Type(typeName, typeofType, toStringTag, constructorName);
13193
}
13294

133-
134-
135-
// Create type testers.
136-
137-
for(const name of TYPE_NAMES){
138-
is[name] = (v)=> is(v).type === name;
95+
function is(value){
96+
return new TypeTest(value);
13997
}
14098

141-
is.object = (v)=> is(v).isObject;
142-
is.primitive = (v)=> is(v).isPrimitive;
143-
144-
is.defined = (v)=> !is.undefined(v);
145-
is.nullish = (v)=> (is.undefined(v) || is.null(v));
146-
147-
is.falsy = (v)=> !v;
148-
is.truthy = (v)=> !!v;
149-
150-
is.numberish = (v)=> (is.number(v) || is.nan(v));
151-
is.real = (v)=> (is.number(v) && Number.isFinite(v instanceof Number ? v.valueOf() : v));
152-
is.infinite = (v)=> (is.number(v) && !Number.isFinite(v instanceof Number ? v.valueOf() : v));
153-
154-
155-
156-
// Create additional methods.
157-
158-
is.empty = (v)=> (v?.length === 0 || v?.size === 0);
159-
160-
is.of = (v, c)=> v instanceof c;
161-
162-
163-
16499
export { is as default };

0 commit comments

Comments
 (0)