is-what 4.1.0

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/src/index.ts ADDED
@@ -0,0 +1,415 @@
1
+ export type AnyFunction = (...args: any[]) => any
2
+ export type AnyAsyncFunction = (...args: any[]) => Promise<any>
3
+ export type AnyClass = new (...args: any[]) => any
4
+ export type PlainObject = Record<string | number | symbol, any>
5
+
6
+ type TypeGuard<A, B extends A> = (payload: A) => payload is B
7
+
8
+ /**
9
+ * Returns the object type of the given payload
10
+ *
11
+ * @param {*} payload
12
+ * @returns {string}
13
+ */
14
+ export function getType(payload: any): string {
15
+ return Object.prototype.toString.call(payload).slice(8, -1)
16
+ }
17
+
18
+ /**
19
+ * Returns whether the payload is undefined
20
+ *
21
+ * @param {*} payload
22
+ * @returns {payload is undefined}
23
+ */
24
+ export function isUndefined(payload: any): payload is undefined {
25
+ return getType(payload) === 'Undefined'
26
+ }
27
+
28
+ /**
29
+ * Returns whether the payload is null
30
+ *
31
+ * @param {*} payload
32
+ * @returns {payload is null}
33
+ */
34
+ export function isNull(payload: any): payload is null {
35
+ return getType(payload) === 'Null'
36
+ }
37
+
38
+ /**
39
+ * Returns whether the payload is a plain JavaScript object (excluding special classes or objects with other prototypes)
40
+ *
41
+ * @param {*} payload
42
+ * @returns {payload is PlainObject}
43
+ */
44
+ export function isPlainObject(payload: any): payload is PlainObject {
45
+ if (getType(payload) !== 'Object') return false
46
+ return payload.constructor === Object && Object.getPrototypeOf(payload) === Object.prototype
47
+ }
48
+
49
+ /**
50
+ * Returns whether the payload is a plain JavaScript object (excluding special classes or objects with other prototypes)
51
+ *
52
+ * @param {*} payload
53
+ * @returns {payload is PlainObject}
54
+ */
55
+ export function isObject(payload: any): payload is PlainObject {
56
+ return isPlainObject(payload)
57
+ }
58
+
59
+ /**
60
+ * Returns whether the payload is a an empty object (excluding special classes or objects with other prototypes)
61
+ *
62
+ * @param {*} payload
63
+ * @returns {payload is { [K in any]: never }}
64
+ */
65
+ export function isEmptyObject(payload: any): payload is { [K in any]: never } {
66
+ return isPlainObject(payload) && Object.keys(payload).length === 0
67
+ }
68
+
69
+ /**
70
+ * Returns whether the payload is a an empty object (excluding special classes or objects with other prototypes)
71
+ *
72
+ * @param {*} payload
73
+ * @returns {payload is PlainObject}
74
+ */
75
+ export function isFullObject(payload: any): payload is PlainObject {
76
+ return isPlainObject(payload) && Object.keys(payload).length > 0
77
+ }
78
+
79
+ /**
80
+ * Returns whether the payload is an any kind of object (including special classes or objects with different prototypes)
81
+ *
82
+ * @param {*} payload
83
+ * @returns {payload is PlainObject}
84
+ */
85
+ export function isAnyObject(payload: any): payload is PlainObject {
86
+ return getType(payload) === 'Object'
87
+ }
88
+
89
+ /**
90
+ * Returns whether the payload is an object like a type passed in < >
91
+ *
92
+ * Usage: isObjectLike<{id: any}>(payload) // will make sure it's an object and has an `id` prop.
93
+ *
94
+ * @template T this must be passed in < >
95
+ * @param {*} payload
96
+ * @returns {payload is T}
97
+ */
98
+ export function isObjectLike<T extends PlainObject>(payload: any): payload is T {
99
+ return isAnyObject(payload)
100
+ }
101
+
102
+ /**
103
+ * Returns whether the payload is a function (regular or async)
104
+ *
105
+ * @param {*} payload
106
+ * @returns {payload is AnyFunction}
107
+ */
108
+ export function isFunction(payload: any): payload is AnyFunction {
109
+ return typeof payload === 'function'
110
+ }
111
+
112
+ /**
113
+ * Returns whether the payload is an array
114
+ *
115
+ * @param {any} payload
116
+ * @returns {payload is any[]}
117
+ */
118
+ export function isArray(payload: any): payload is any[] {
119
+ return getType(payload) === 'Array'
120
+ }
121
+
122
+ /**
123
+ * Returns whether the payload is a an array with at least 1 item
124
+ *
125
+ * @param {*} payload
126
+ * @returns {payload is any[]}
127
+ */
128
+ export function isFullArray(payload: any): payload is any[] {
129
+ return isArray(payload) && payload.length > 0
130
+ }
131
+
132
+ /**
133
+ * Returns whether the payload is a an empty array
134
+ *
135
+ * @param {*} payload
136
+ * @returns {payload is []}
137
+ */
138
+ export function isEmptyArray(payload: any): payload is [] {
139
+ return isArray(payload) && payload.length === 0
140
+ }
141
+
142
+ /**
143
+ * Returns whether the payload is a string
144
+ *
145
+ * @param {*} payload
146
+ * @returns {payload is string}
147
+ */
148
+ export function isString(payload: any): payload is string {
149
+ return getType(payload) === 'String'
150
+ }
151
+
152
+ /**
153
+ * Returns whether the payload is a string, BUT returns false for ''
154
+ *
155
+ * @param {*} payload
156
+ * @returns {payload is string}
157
+ */
158
+ export function isFullString(payload: any): payload is string {
159
+ return isString(payload) && payload !== ''
160
+ }
161
+
162
+ /**
163
+ * Returns whether the payload is ''
164
+ *
165
+ * @param {*} payload
166
+ * @returns {payload is string}
167
+ */
168
+ export function isEmptyString(payload: any): payload is string {
169
+ return payload === ''
170
+ }
171
+
172
+ /**
173
+ * Returns whether the payload is a number (but not NaN)
174
+ *
175
+ * This will return `false` for `NaN`!!
176
+ *
177
+ * @param {*} payload
178
+ * @returns {payload is number}
179
+ */
180
+ export function isNumber(payload: any): payload is number {
181
+ return getType(payload) === 'Number' && !isNaN(payload)
182
+ }
183
+
184
+ /**
185
+ * Returns whether the payload is a positive number (but not 0)
186
+ *
187
+ * @param {*} payload
188
+ * @returns {payload is number}
189
+ */
190
+ export function isPositiveNumber(payload: any): payload is number {
191
+ return isNumber(payload) && payload > 0
192
+ }
193
+
194
+ /**
195
+ * Returns whether the payload is a negative number (but not 0)
196
+ *
197
+ * @param {*} payload
198
+ * @returns {payload is number}
199
+ */
200
+ export function isNegativeNumber(payload: any): payload is number {
201
+ return isNumber(payload) && payload < 0
202
+ }
203
+
204
+ /**
205
+ * Returns whether the payload is a boolean
206
+ *
207
+ * @param {*} payload
208
+ * @returns {payload is boolean}
209
+ */
210
+ export function isBoolean(payload: any): payload is boolean {
211
+ return getType(payload) === 'Boolean'
212
+ }
213
+
214
+ /**
215
+ * Returns whether the payload is a regular expression (RegExp)
216
+ *
217
+ * @param {*} payload
218
+ * @returns {payload is RegExp}
219
+ */
220
+ export function isRegExp(payload: any): payload is RegExp {
221
+ return getType(payload) === 'RegExp'
222
+ }
223
+
224
+ /**
225
+ * Returns whether the payload is a Map
226
+ *
227
+ * @param {*} payload
228
+ * @returns {payload is Map<any, any>}
229
+ */
230
+ export function isMap(payload: any): payload is Map<any, any> {
231
+ return getType(payload) === 'Map'
232
+ }
233
+
234
+ /**
235
+ * Returns whether the payload is a WeakMap
236
+ *
237
+ * @param {*} payload
238
+ * @returns {payload is WeakMap<any, any>}
239
+ */
240
+ export function isWeakMap(payload: any): payload is WeakMap<any, any> {
241
+ return getType(payload) === 'WeakMap'
242
+ }
243
+
244
+ /**
245
+ * Returns whether the payload is a Set
246
+ *
247
+ * @param {*} payload
248
+ * @returns {payload is Set<any>}
249
+ */
250
+ export function isSet(payload: any): payload is Set<any> {
251
+ return getType(payload) === 'Set'
252
+ }
253
+
254
+ /**
255
+ * Returns whether the payload is a WeakSet
256
+ *
257
+ * @param {*} payload
258
+ * @returns {payload is WeakSet<any>}
259
+ */
260
+ export function isWeakSet(payload: any): payload is WeakSet<any> {
261
+ return getType(payload) === 'WeakSet'
262
+ }
263
+
264
+ /**
265
+ * Returns whether the payload is a Symbol
266
+ *
267
+ * @param {*} payload
268
+ * @returns {payload is symbol}
269
+ */
270
+ export function isSymbol(payload: any): payload is symbol {
271
+ return getType(payload) === 'Symbol'
272
+ }
273
+
274
+ /**
275
+ * Returns whether the payload is a Date, and that the date is valid
276
+ *
277
+ * @param {*} payload
278
+ * @returns {payload is Date}
279
+ */
280
+ export function isDate(payload: any): payload is Date {
281
+ return getType(payload) === 'Date' && !isNaN(payload)
282
+ }
283
+
284
+ /**
285
+ * Returns whether the payload is a Blob
286
+ *
287
+ * @param {*} payload
288
+ * @returns {payload is Blob}
289
+ */
290
+ export function isBlob(payload: any): payload is Blob {
291
+ return getType(payload) === 'Blob'
292
+ }
293
+
294
+ /**
295
+ * Returns whether the payload is a File
296
+ *
297
+ * @param {*} payload
298
+ * @returns {payload is File}
299
+ */
300
+ export function isFile(payload: any): payload is File {
301
+ return getType(payload) === 'File'
302
+ }
303
+
304
+ /**
305
+ * Returns whether the payload is a Promise
306
+ *
307
+ * @param {*} payload
308
+ * @returns {payload is Promise<any>}
309
+ */
310
+ export function isPromise(payload: any): payload is Promise<any> {
311
+ return getType(payload) === 'Promise'
312
+ }
313
+
314
+ /**
315
+ * Returns whether the payload is an Error
316
+ *
317
+ * @param {*} payload
318
+ * @returns {payload is Error}
319
+ */
320
+ export function isError(payload: any): payload is Error {
321
+ return getType(payload) === 'Error'
322
+ }
323
+
324
+ /**
325
+ * Returns whether the payload is literally the value `NaN` (it's `NaN` and also a `number`)
326
+ *
327
+ * @param {*} payload
328
+ * @returns {payload is typeof NaN}
329
+ */
330
+ export function isNaNValue(payload: any): payload is typeof NaN {
331
+ return getType(payload) === 'Number' && isNaN(payload)
332
+ }
333
+
334
+ /**
335
+ * Returns whether the payload is a primitive type (eg. Boolean | Null | Undefined | Number | String | Symbol)
336
+ *
337
+ * @param {*} payload
338
+ * @returns {(payload is boolean | null | undefined | number | string | symbol)}
339
+ */
340
+ export function isPrimitive(
341
+ payload: any
342
+ ): payload is boolean | null | undefined | number | string | symbol {
343
+ return (
344
+ isBoolean(payload) ||
345
+ isNull(payload) ||
346
+ isUndefined(payload) ||
347
+ isNumber(payload) ||
348
+ isString(payload) ||
349
+ isSymbol(payload)
350
+ )
351
+ }
352
+
353
+ /**
354
+ * Returns true whether the payload is null or undefined
355
+ *
356
+ * @param {*} payload
357
+ * @returns {(payload is null | undefined)}
358
+ */
359
+ export const isNullOrUndefined = isOneOf(isNull, isUndefined)
360
+
361
+ export function isOneOf<A, B extends A, C extends A>(
362
+ a: TypeGuard<A, B>,
363
+ b: TypeGuard<A, C>
364
+ ): TypeGuard<A, B | C>
365
+ export function isOneOf<A, B extends A, C extends A, D extends A>(
366
+ a: TypeGuard<A, B>,
367
+ b: TypeGuard<A, C>,
368
+ c: TypeGuard<A, D>
369
+ ): TypeGuard<A, B | C | D>
370
+ export function isOneOf<A, B extends A, C extends A, D extends A, E extends A>(
371
+ a: TypeGuard<A, B>,
372
+ b: TypeGuard<A, C>,
373
+ c: TypeGuard<A, D>,
374
+ d: TypeGuard<A, E>
375
+ ): TypeGuard<A, B | C | D | E>
376
+ export function isOneOf<A, B extends A, C extends A, D extends A, E extends A, F extends A>(
377
+ a: TypeGuard<A, B>,
378
+ b: TypeGuard<A, C>,
379
+ c: TypeGuard<A, D>,
380
+ d: TypeGuard<A, E>,
381
+ e: TypeGuard<A, F>
382
+ ): TypeGuard<A, B | C | D | E | F>
383
+ export function isOneOf(
384
+ a: AnyFunction,
385
+ b: AnyFunction,
386
+ c?: AnyFunction,
387
+ d?: AnyFunction,
388
+ e?: AnyFunction
389
+ ): (value: unknown) => boolean {
390
+ return (value) =>
391
+ a(value) || b(value) || (!!c && c(value)) || (!!d && d(value)) || (!!e && e(value))
392
+ }
393
+
394
+ /**
395
+ * Does a generic check to check that the given payload is of a given type.
396
+ * In cases like Number, it will return true for NaN as NaN is a Number (thanks javascript!);
397
+ * It will, however, differentiate between object and null
398
+ *
399
+ * @template T
400
+ * @param {*} payload
401
+ * @param {T} type
402
+ * @throws {TypeError} Will throw type error if type is an invalid type
403
+ * @returns {payload is T}
404
+ */
405
+ export function isType<T extends AnyFunction | AnyClass>(payload: any, type: T): payload is T {
406
+ if (!(type instanceof Function)) {
407
+ throw new TypeError('Type must be a function')
408
+ }
409
+ if (!Object.prototype.hasOwnProperty.call(type, 'prototype')) {
410
+ throw new TypeError('Type is not a class')
411
+ }
412
+ // Classes usually have names (as functions usually have names)
413
+ const name: string | undefined | null = (type as any).name
414
+ return getType(payload) === name || Boolean(payload && payload.constructor === type)
415
+ }