is-what 4.0.0 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # is What? 🙉
2
2
 
3
+ <a href="https://www.npmjs.com/package/is-what"><img src="https://img.shields.io/npm/v/is-what.svg" alt="Total Downloads"></a>
4
+ <a href="https://www.npmjs.com/package/is-what"><img src="https://img.shields.io/npm/dw/is-what.svg" alt="Latest Stable Version"></a>
5
+
3
6
  Very simple & small JS type check functions. It's fully TypeScript supported!
4
7
 
5
8
  ```
@@ -36,6 +39,12 @@ import { isString, isDate, isPlainObject } from 'is-what'
36
39
  ### Simple type check functions
37
40
 
38
41
  ```js
42
+ // basics
43
+ isBoolean(true) // true
44
+ isBoolean(false) // true
45
+ isUndefined(undefined) // true
46
+ isNull(null) // true
47
+
39
48
  // strings
40
49
  isString('') // true
41
50
  isEmptyString('') // true
@@ -43,38 +52,86 @@ isFullString('') // false
43
52
 
44
53
  // numbers
45
54
  isNumber(0) // true
46
- isNumber(NaN) // false
55
+ isNumber('0') // false
56
+ isNumber(NaN) // false *
57
+ isPositiveNumber(1) // true
58
+ isNegativeNumber(-1) // true
59
+ // * see below for special NaN use cases!
60
+
61
+ // arrays
62
+ isArray([]) // true
63
+ isEmptyArray([]) // true
64
+ isFullArray([1]) // true
65
+
66
+ // objects
67
+ isPlainObject({}) // true *
68
+ isEmptyObject({}) // true
69
+ isFullObject({ a: 1 }) // true
70
+ // * see below for special object (& class instance) use cases!
71
+
72
+ // functions
73
+ isFunction(function () {}) // true
74
+ isFunction(() => {}) // true
47
75
 
48
76
  // dates
49
77
  isDate(new Date()) // true
50
78
  isDate(new Date('invalid date')) // false
51
79
 
80
+ // maps & sets
81
+ isMap(new Map()) // true
82
+ isSet(new Set()) // true
83
+ isWeakMap(new WeakMap()) // true
84
+ isWeakSet(new WeakSet()) // true
85
+
52
86
  // others
53
- isBoolean(false) // true
54
- isFunction(function () {}) // true
55
- isArray([]) // true
56
- isUndefined(undefined) // true
57
- isNull(null) // true
58
87
  isRegExp(/\s/gi) // true
59
88
  isSymbol(Symbol()) // true
60
89
  isBlob(new Blob()) // true
61
90
  isFile(new File([''], '', { type: 'text/html' })) // true
91
+ isError(new Error('')) // true
92
+ isPromise(new Promise((resolve) => {})) // true
62
93
 
63
94
  // primitives
64
95
  isPrimitive('') // true
65
96
  // true for any of: boolean, null, undefined, number, string, symbol
66
97
  ```
67
98
 
68
- ### Getting and checking for specific types
99
+ ### Let's talk about NaN
69
100
 
70
- You can check for specific types with `getType` and `isType`:
101
+ `isNaN` is a built-in JS Function but it really makes no sense:
71
102
 
72
103
  ```js
73
- import { getType, isType } from 'is-what'
104
+ // 1)
105
+ typeof NaN === 'number' // true
106
+ // 🤔 ("not a number" is a "number"...)
74
107
 
75
- getType('') // returns 'String'
76
- // pass a Type as second param:
77
- isType('', String) // returns true
108
+ // 2)
109
+ isNaN('1') // false
110
+ // 🤔 the string '1' is not-"not a number"... so it's a number??
111
+
112
+ // 3)
113
+ isNaN('one') // true
114
+ // 🤔 'one' is NaN but `NaN === 'one'` is false...
115
+ ```
116
+
117
+ With is-what the way we treat NaN makes a little bit more sense:
118
+
119
+ ```js
120
+ import { isNumber, isNaNValue } from 'is-what'
121
+
122
+ // 1)
123
+ isNumber(NaN) // false!
124
+ // let's not treat NaN as a number
125
+
126
+ // 2)
127
+ isNaNValue('1') // false
128
+ // if it's not NaN, it's not NaN!!
129
+
130
+ // 3)
131
+ isNaNValue('one') // false
132
+ // if it's not NaN, it's not NaN!!
133
+
134
+ isNaNValue(NaN) // true
78
135
  ```
79
136
 
80
137
  ### isPlainObject vs isAnyObject
@@ -109,6 +166,18 @@ getType(specialObject) // returns 'Object'
109
166
 
110
167
  > Please note that `isPlainObject` will only return `true` for normal plain JavaScript objects.
111
168
 
169
+ ### Getting and checking for specific types
170
+
171
+ You can check for specific types with `getType` and `isType`:
172
+
173
+ ```js
174
+ import { getType, isType } from 'is-what'
175
+
176
+ getType('') // returns 'String'
177
+ // pass a Type as second param:
178
+ isType('', String) // returns true
179
+ ```
180
+
112
181
  ## TypeScript
113
182
 
114
183
  is-what makes TypeScript know the type during if statements. This means that a check returns the type of the payload for TypeScript users.
@@ -141,16 +210,30 @@ if (isPlainObject(payload) && payload.id) return payload.id
141
210
 
142
211
  ### isObjectLike
143
212
 
144
- If you want more control over which kind of objects are allowed you can use `isObjectLike<T>`:
213
+ If you want more control over what kind of interface/type is casted when checking for objects.
214
+
215
+ To cast to a specific type while checking for `isAnyObject`, can use `isObjectLike<T>`:
145
216
 
146
217
  ```ts
147
218
  import { isObjectLike } from 'is-what'
148
- // usage examples:
149
- isObjectLike<{ specificKey: string }>(payload)
150
- isObjectLike<object>(payload)
151
- // you can pass a specific type for TS to check on.
219
+
220
+ const payload = { name: 'Mesqueeb' } // current type: `{ name: string }`
221
+
222
+ // Without casting:
223
+ if (isAnyObject(payload)) {
224
+ // in here `payload` is casted to: `Record<string | number | symbol, any>`
225
+ // WE LOOSE THE TYPE!
226
+ }
227
+
228
+ // With casting:
229
+ // you can pass a specific type for TS that will be casted when the function returns
230
+ if (isObjectLike<{ name: string }>(payload)) {
231
+ // in here `payload` is casted to: `{ name: string }`
232
+ }
152
233
  ```
153
234
 
235
+ Please note: this library will not actually check the shape of the object, you need to do that yourself.
236
+
154
237
  `isObjectLike<T>` works like this under the hood:
155
238
 
156
239
  ```ts
package/dist/index.cjs ADDED
@@ -0,0 +1,382 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /**
6
+ * Returns the object type of the given payload
7
+ *
8
+ * @param {*} payload
9
+ * @returns {string}
10
+ */
11
+ function getType(payload) {
12
+ return Object.prototype.toString.call(payload).slice(8, -1);
13
+ }
14
+ /**
15
+ * Returns whether the payload is undefined
16
+ *
17
+ * @param {*} payload
18
+ * @returns {payload is undefined}
19
+ */
20
+ function isUndefined(payload) {
21
+ return getType(payload) === 'Undefined';
22
+ }
23
+ /**
24
+ * Returns whether the payload is null
25
+ *
26
+ * @param {*} payload
27
+ * @returns {payload is null}
28
+ */
29
+ function isNull(payload) {
30
+ return getType(payload) === 'Null';
31
+ }
32
+ /**
33
+ * Returns whether the payload is a plain JavaScript object (excluding special classes or objects with other prototypes)
34
+ *
35
+ * @param {*} payload
36
+ * @returns {payload is PlainObject}
37
+ */
38
+ function isPlainObject(payload) {
39
+ if (getType(payload) !== 'Object')
40
+ return false;
41
+ return payload.constructor === Object && Object.getPrototypeOf(payload) === Object.prototype;
42
+ }
43
+ /**
44
+ * Returns whether the payload is a plain JavaScript object (excluding special classes or objects with other prototypes)
45
+ *
46
+ * @param {*} payload
47
+ * @returns {payload is PlainObject}
48
+ */
49
+ function isObject(payload) {
50
+ return isPlainObject(payload);
51
+ }
52
+ /**
53
+ * Returns whether the payload is a an empty object (excluding special classes or objects with other prototypes)
54
+ *
55
+ * @param {*} payload
56
+ * @returns {payload is { [K in any]: never }}
57
+ */
58
+ function isEmptyObject(payload) {
59
+ return isPlainObject(payload) && Object.keys(payload).length === 0;
60
+ }
61
+ /**
62
+ * Returns whether the payload is a an empty object (excluding special classes or objects with other prototypes)
63
+ *
64
+ * @param {*} payload
65
+ * @returns {payload is PlainObject}
66
+ */
67
+ function isFullObject(payload) {
68
+ return isPlainObject(payload) && Object.keys(payload).length > 0;
69
+ }
70
+ /**
71
+ * Returns whether the payload is an any kind of object (including special classes or objects with different prototypes)
72
+ *
73
+ * @param {*} payload
74
+ * @returns {payload is PlainObject}
75
+ */
76
+ function isAnyObject(payload) {
77
+ return getType(payload) === 'Object';
78
+ }
79
+ /**
80
+ * Returns whether the payload is an object like a type passed in < >
81
+ *
82
+ * Usage: isObjectLike<{id: any}>(payload) // will make sure it's an object and has an `id` prop.
83
+ *
84
+ * @template T this must be passed in < >
85
+ * @param {*} payload
86
+ * @returns {payload is T}
87
+ */
88
+ function isObjectLike(payload) {
89
+ return isAnyObject(payload);
90
+ }
91
+ /**
92
+ * Returns whether the payload is a function (regular or async)
93
+ *
94
+ * @param {*} payload
95
+ * @returns {payload is AnyFunction}
96
+ */
97
+ function isFunction(payload) {
98
+ return typeof payload === 'function';
99
+ }
100
+ /**
101
+ * Returns whether the payload is an array
102
+ *
103
+ * @param {any} payload
104
+ * @returns {payload is any[]}
105
+ */
106
+ function isArray(payload) {
107
+ return getType(payload) === 'Array';
108
+ }
109
+ /**
110
+ * Returns whether the payload is a an array with at least 1 item
111
+ *
112
+ * @param {*} payload
113
+ * @returns {payload is any[]}
114
+ */
115
+ function isFullArray(payload) {
116
+ return isArray(payload) && payload.length > 0;
117
+ }
118
+ /**
119
+ * Returns whether the payload is a an empty array
120
+ *
121
+ * @param {*} payload
122
+ * @returns {payload is []}
123
+ */
124
+ function isEmptyArray(payload) {
125
+ return isArray(payload) && payload.length === 0;
126
+ }
127
+ /**
128
+ * Returns whether the payload is a string
129
+ *
130
+ * @param {*} payload
131
+ * @returns {payload is string}
132
+ */
133
+ function isString(payload) {
134
+ return getType(payload) === 'String';
135
+ }
136
+ /**
137
+ * Returns whether the payload is a string, BUT returns false for ''
138
+ *
139
+ * @param {*} payload
140
+ * @returns {payload is string}
141
+ */
142
+ function isFullString(payload) {
143
+ return isString(payload) && payload !== '';
144
+ }
145
+ /**
146
+ * Returns whether the payload is ''
147
+ *
148
+ * @param {*} payload
149
+ * @returns {payload is string}
150
+ */
151
+ function isEmptyString(payload) {
152
+ return payload === '';
153
+ }
154
+ /**
155
+ * Returns whether the payload is a number (but not NaN)
156
+ *
157
+ * This will return `false` for `NaN`!!
158
+ *
159
+ * @param {*} payload
160
+ * @returns {payload is number}
161
+ */
162
+ function isNumber(payload) {
163
+ return getType(payload) === 'Number' && !isNaN(payload);
164
+ }
165
+ /**
166
+ * Returns whether the payload is a positive number (but not 0)
167
+ *
168
+ * @param {*} payload
169
+ * @returns {payload is number}
170
+ */
171
+ function isPositiveNumber(payload) {
172
+ return isNumber(payload) && payload > 0;
173
+ }
174
+ /**
175
+ * Returns whether the payload is a negative number (but not 0)
176
+ *
177
+ * @param {*} payload
178
+ * @returns {payload is number}
179
+ */
180
+ function isNegativeNumber(payload) {
181
+ return isNumber(payload) && payload < 0;
182
+ }
183
+ /**
184
+ * Returns whether the payload is a boolean
185
+ *
186
+ * @param {*} payload
187
+ * @returns {payload is boolean}
188
+ */
189
+ function isBoolean(payload) {
190
+ return getType(payload) === 'Boolean';
191
+ }
192
+ /**
193
+ * Returns whether the payload is a regular expression (RegExp)
194
+ *
195
+ * @param {*} payload
196
+ * @returns {payload is RegExp}
197
+ */
198
+ function isRegExp(payload) {
199
+ return getType(payload) === 'RegExp';
200
+ }
201
+ /**
202
+ * Returns whether the payload is a Map
203
+ *
204
+ * @param {*} payload
205
+ * @returns {payload is Map<any, any>}
206
+ */
207
+ function isMap(payload) {
208
+ return getType(payload) === 'Map';
209
+ }
210
+ /**
211
+ * Returns whether the payload is a WeakMap
212
+ *
213
+ * @param {*} payload
214
+ * @returns {payload is WeakMap<any, any>}
215
+ */
216
+ function isWeakMap(payload) {
217
+ return getType(payload) === 'WeakMap';
218
+ }
219
+ /**
220
+ * Returns whether the payload is a Set
221
+ *
222
+ * @param {*} payload
223
+ * @returns {payload is Set<any>}
224
+ */
225
+ function isSet(payload) {
226
+ return getType(payload) === 'Set';
227
+ }
228
+ /**
229
+ * Returns whether the payload is a WeakSet
230
+ *
231
+ * @param {*} payload
232
+ * @returns {payload is WeakSet<any>}
233
+ */
234
+ function isWeakSet(payload) {
235
+ return getType(payload) === 'WeakSet';
236
+ }
237
+ /**
238
+ * Returns whether the payload is a Symbol
239
+ *
240
+ * @param {*} payload
241
+ * @returns {payload is symbol}
242
+ */
243
+ function isSymbol(payload) {
244
+ return getType(payload) === 'Symbol';
245
+ }
246
+ /**
247
+ * Returns whether the payload is a Date, and that the date is valid
248
+ *
249
+ * @param {*} payload
250
+ * @returns {payload is Date}
251
+ */
252
+ function isDate(payload) {
253
+ return getType(payload) === 'Date' && !isNaN(payload);
254
+ }
255
+ /**
256
+ * Returns whether the payload is a Blob
257
+ *
258
+ * @param {*} payload
259
+ * @returns {payload is Blob}
260
+ */
261
+ function isBlob(payload) {
262
+ return getType(payload) === 'Blob';
263
+ }
264
+ /**
265
+ * Returns whether the payload is a File
266
+ *
267
+ * @param {*} payload
268
+ * @returns {payload is File}
269
+ */
270
+ function isFile(payload) {
271
+ return getType(payload) === 'File';
272
+ }
273
+ /**
274
+ * Returns whether the payload is a Promise
275
+ *
276
+ * @param {*} payload
277
+ * @returns {payload is Promise<any>}
278
+ */
279
+ function isPromise(payload) {
280
+ return getType(payload) === 'Promise';
281
+ }
282
+ /**
283
+ * Returns whether the payload is an Error
284
+ *
285
+ * @param {*} payload
286
+ * @returns {payload is Error}
287
+ */
288
+ function isError(payload) {
289
+ return getType(payload) === 'Error';
290
+ }
291
+ /**
292
+ * Returns whether the payload is literally the value `NaN` (it's `NaN` and also a `number`)
293
+ *
294
+ * @param {*} payload
295
+ * @returns {payload is typeof NaN}
296
+ */
297
+ function isNaNValue(payload) {
298
+ return getType(payload) === 'Number' && isNaN(payload);
299
+ }
300
+ /**
301
+ * Returns whether the payload is a primitive type (eg. Boolean | Null | Undefined | Number | String | Symbol)
302
+ *
303
+ * @param {*} payload
304
+ * @returns {(payload is boolean | null | undefined | number | string | symbol)}
305
+ */
306
+ function isPrimitive(payload) {
307
+ return (isBoolean(payload) ||
308
+ isNull(payload) ||
309
+ isUndefined(payload) ||
310
+ isNumber(payload) ||
311
+ isString(payload) ||
312
+ isSymbol(payload));
313
+ }
314
+ /**
315
+ * Returns true whether the payload is null or undefined
316
+ *
317
+ * @param {*} payload
318
+ * @returns {(payload is null | undefined)}
319
+ */
320
+ const isNullOrUndefined = isOneOf(isNull, isUndefined);
321
+ function isOneOf(a, b, c, d, e) {
322
+ return (value) => a(value) || b(value) || (!!c && c(value)) || (!!d && d(value)) || (!!e && e(value));
323
+ }
324
+ /**
325
+ * Does a generic check to check that the given payload is of a given type.
326
+ * In cases like Number, it will return true for NaN as NaN is a Number (thanks javascript!);
327
+ * It will, however, differentiate between object and null
328
+ *
329
+ * @template T
330
+ * @param {*} payload
331
+ * @param {T} type
332
+ * @throws {TypeError} Will throw type error if type is an invalid type
333
+ * @returns {payload is T}
334
+ */
335
+ function isType(payload, type) {
336
+ if (!(type instanceof Function)) {
337
+ throw new TypeError('Type must be a function');
338
+ }
339
+ if (!Object.prototype.hasOwnProperty.call(type, 'prototype')) {
340
+ throw new TypeError('Type is not a class');
341
+ }
342
+ // Classes usually have names (as functions usually have names)
343
+ const name = type.name;
344
+ return getType(payload) === name || Boolean(payload && payload.constructor === type);
345
+ }
346
+
347
+ exports.getType = getType;
348
+ exports.isAnyObject = isAnyObject;
349
+ exports.isArray = isArray;
350
+ exports.isBlob = isBlob;
351
+ exports.isBoolean = isBoolean;
352
+ exports.isDate = isDate;
353
+ exports.isEmptyArray = isEmptyArray;
354
+ exports.isEmptyObject = isEmptyObject;
355
+ exports.isEmptyString = isEmptyString;
356
+ exports.isError = isError;
357
+ exports.isFile = isFile;
358
+ exports.isFullArray = isFullArray;
359
+ exports.isFullObject = isFullObject;
360
+ exports.isFullString = isFullString;
361
+ exports.isFunction = isFunction;
362
+ exports.isMap = isMap;
363
+ exports.isNaNValue = isNaNValue;
364
+ exports.isNegativeNumber = isNegativeNumber;
365
+ exports.isNull = isNull;
366
+ exports.isNullOrUndefined = isNullOrUndefined;
367
+ exports.isNumber = isNumber;
368
+ exports.isObject = isObject;
369
+ exports.isObjectLike = isObjectLike;
370
+ exports.isOneOf = isOneOf;
371
+ exports.isPlainObject = isPlainObject;
372
+ exports.isPositiveNumber = isPositiveNumber;
373
+ exports.isPrimitive = isPrimitive;
374
+ exports.isPromise = isPromise;
375
+ exports.isRegExp = isRegExp;
376
+ exports.isSet = isSet;
377
+ exports.isString = isString;
378
+ exports.isSymbol = isSymbol;
379
+ exports.isType = isType;
380
+ exports.isUndefined = isUndefined;
381
+ exports.isWeakMap = isWeakMap;
382
+ exports.isWeakSet = isWeakSet;
@@ -158,6 +158,24 @@ function isEmptyString(payload) {
158
158
  function isNumber(payload) {
159
159
  return getType(payload) === 'Number' && !isNaN(payload);
160
160
  }
161
+ /**
162
+ * Returns whether the payload is a positive number (but not 0)
163
+ *
164
+ * @param {*} payload
165
+ * @returns {payload is number}
166
+ */
167
+ function isPositiveNumber(payload) {
168
+ return isNumber(payload) && payload > 0;
169
+ }
170
+ /**
171
+ * Returns whether the payload is a negative number (but not 0)
172
+ *
173
+ * @param {*} payload
174
+ * @returns {payload is number}
175
+ */
176
+ function isNegativeNumber(payload) {
177
+ return isNumber(payload) && payload < 0;
178
+ }
161
179
  /**
162
180
  * Returns whether the payload is a boolean
163
181
  *
@@ -322,4 +340,4 @@ function isType(payload, type) {
322
340
  return getType(payload) === name || Boolean(payload && payload.constructor === type);
323
341
  }
324
342
 
325
- export { getType, isAnyObject, isArray, isBlob, isBoolean, isDate, isEmptyArray, isEmptyObject, isEmptyString, isError, isFile, isFullArray, isFullObject, isFullString, isFunction, isMap, isNaNValue, isNull, isNullOrUndefined, isNumber, isObject, isObjectLike, isOneOf, isPlainObject, isPrimitive, isPromise, isRegExp, isSet, isString, isSymbol, isType, isUndefined, isWeakMap, isWeakSet };
343
+ export { getType, isAnyObject, isArray, isBlob, isBoolean, isDate, isEmptyArray, isEmptyObject, isEmptyString, isError, isFile, isFullArray, isFullObject, isFullString, isFunction, isMap, isNaNValue, isNegativeNumber, isNull, isNullOrUndefined, isNumber, isObject, isObjectLike, isOneOf, isPlainObject, isPositiveNumber, isPrimitive, isPromise, isRegExp, isSet, isString, isSymbol, isType, isUndefined, isWeakMap, isWeakSet };
@@ -129,6 +129,20 @@ export declare function isEmptyString(payload: any): payload is string;
129
129
  * @returns {payload is number}
130
130
  */
131
131
  export declare function isNumber(payload: any): payload is number;
132
+ /**
133
+ * Returns whether the payload is a positive number (but not 0)
134
+ *
135
+ * @param {*} payload
136
+ * @returns {payload is number}
137
+ */
138
+ export declare function isPositiveNumber(payload: any): payload is number;
139
+ /**
140
+ * Returns whether the payload is a negative number (but not 0)
141
+ *
142
+ * @param {*} payload
143
+ * @returns {payload is number}
144
+ */
145
+ export declare function isNegativeNumber(payload: any): payload is number;
132
146
  /**
133
147
  * Returns whether the payload is a boolean
134
148
  *