UNPKG

17.4 kBMarkdownView Raw
1# is
2
3> Type check values
4
5For example, `is.string('🦄') //=> true`
6
7<img src="header.gif" width="182" align="right">
8
9## Highlights
10
11- Written in TypeScript
12- [Extensive use of type guards](#type-guards)
13- [Supports type assertions](#type-assertions)
14- [Aware of generic type parameters](#generic-type-parameters) (use with caution)
15- Actively maintained
16- ![Millions of downloads per week](https://img.shields.io/npm/dw/@sindresorhus/is)
17
18## Install
19
20```sh
21npm install @sindresorhus/is
22```
23
24## Usage
25
26```js
27import is from '@sindresorhus/is';
28
29is('🦄');
30//=> 'string'
31
32is(new Map());
33//=> 'Map'
34
35is.number(6);
36//=> true
37```
38
39[Assertions](#type-assertions) perform the same type checks, but throw an error if the type does not match.
40
41```js
42import {assert} from '@sindresorhus/is';
43
44assert.string(2);
45//=> Error: Expected value which is `string`, received value of type `number`.
46```
47
48And with TypeScript:
49
50```ts
51import {assert} from '@sindresorhus/is';
52
53assert.string(foo);
54// `foo` is now typed as a `string`.
55```
56
57## API
58
59### is(value)
60
61Returns the type of `value`.
62
63Primitives are lowercase and object types are camelcase.
64
65Example:
66
67- `'undefined'`
68- `'null'`
69- `'string'`
70- `'symbol'`
71- `'Array'`
72- `'Function'`
73- `'Object'`
74
75Note: It will throw an error if you try to feed it object-wrapped primitives, as that's a bad practice. For example `new String('foo')`.
76
77### is.{method}
78
79All the below methods accept a value and returns a boolean for whether the value is of the desired type.
80
81#### Primitives
82
83##### .undefined(value)
84##### .null(value)
85
86**Note:** TypeScript users must use `.null_()` because of a TypeScript naming limitation.
87
88##### .string(value)
89##### .number(value)
90
91Note: `is.number(NaN)` returns `false`. This intentionally deviates from `typeof` behavior to increase user-friendliness of `is` type checks.
92
93##### .boolean(value)
94##### .symbol(value)
95##### .bigint(value)
96
97#### Built-in types
98
99##### .array(value, assertion?)
100
101Returns true if `value` is an array and all of its items match the assertion (if provided).
102
103```js
104is.array(value); // Validate `value` is an array.
105is.array(value, is.number); // Validate `value` is an array and all of its items are numbers.
106```
107
108##### .function(value)
109
110**Note:** TypeScript users must use `.function_()` because of a TypeScript naming limitation.
111
112##### .buffer(value)
113##### .blob(value)
114##### .object(value)
115
116Keep in mind that [functions are objects too](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions).
117
118##### .numericString(value)
119
120Returns `true` for a string that represents a number satisfying `is.number`, for example, `'42'` and `'-8.3'`.
121
122Note: `'NaN'` returns `false`, but `'Infinity'` and `'-Infinity'` return `true`.
123
124##### .regExp(value)
125##### .date(value)
126##### .error(value)
127##### .nativePromise(value)
128##### .promise(value)
129
130Returns `true` for any object with a `.then()` and `.catch()` method. Prefer this one over `.nativePromise()` as you usually want to allow userland promise implementations too.
131
132##### .generator(value)
133
134Returns `true` for any object that implements its own `.next()` and `.throw()` methods and has a function definition for `Symbol.iterator`.
135
136##### .generatorFunction(value)
137
138##### .asyncFunction(value)
139
140Returns `true` for any `async` function that can be called with the `await` operator.
141
142```js
143is.asyncFunction(async () => {});
144//=> true
145
146is.asyncFunction(() => {});
147//=> false
148```
149
150##### .asyncGenerator(value)
151
152```js
153is.asyncGenerator(
154 (async function * () {
155 yield 4;
156 })()
157);
158//=> true
159
160is.asyncGenerator(
161 (function * () {
162 yield 4;
163 })()
164);
165//=> false
166```
167
168##### .asyncGeneratorFunction(value)
169
170```js
171is.asyncGeneratorFunction(async function * () {
172 yield 4;
173});
174//=> true
175
176is.asyncGeneratorFunction(function * () {
177 yield 4;
178});
179//=> false
180```
181
182##### .boundFunction(value)
183
184Returns `true` for any `bound` function.
185
186```js
187is.boundFunction(() => {});
188//=> true
189
190is.boundFunction(function () {}.bind(null));
191//=> true
192
193is.boundFunction(function () {});
194//=> false
195```
196
197##### .map(value)
198##### .set(value)
199##### .weakMap(value)
200##### .weakSet(value)
201##### .weakRef(value)
202
203#### Typed arrays
204
205##### .int8Array(value)
206##### .uint8Array(value)
207##### .uint8ClampedArray(value)
208##### .int16Array(value)
209##### .uint16Array(value)
210##### .int32Array(value)
211##### .uint32Array(value)
212##### .float32Array(value)
213##### .float64Array(value)
214##### .bigInt64Array(value)
215##### .bigUint64Array(value)
216
217#### Structured data
218
219##### .arrayBuffer(value)
220##### .sharedArrayBuffer(value)
221##### .dataView(value)
222
223##### .enumCase(value, enum)
224
225TypeScript-only. Returns `true` if `value` is a member of `enum`.
226
227```ts
228enum Direction {
229 Ascending = 'ascending',
230 Descending = 'descending'
231}
232
233is.enumCase('ascending', Direction);
234//=> true
235
236is.enumCase('other', Direction);
237//=> false
238```
239
240#### Emptiness
241
242##### .emptyString(value)
243
244Returns `true` if the value is a `string` and the `.length` is 0.
245
246##### .emptyStringOrWhitespace(value)
247
248Returns `true` if `is.emptyString(value)` or if it's a `string` that is all whitespace.
249
250##### .nonEmptyString(value)
251
252Returns `true` if the value is a `string` and the `.length` is more than 0.
253
254##### .nonEmptyStringAndNotWhitespace(value)
255
256Returns `true` if the value is a `string` that is not empty and not whitespace.
257
258```js
259const values = ['property1', '', null, 'property2', ' ', undefined];
260
261values.filter(is.nonEmptyStringAndNotWhitespace);
262//=> ['property1', 'property2']
263```
264
265##### .emptyArray(value)
266
267Returns `true` if the value is an `Array` and the `.length` is 0.
268
269##### .nonEmptyArray(value)
270
271Returns `true` if the value is an `Array` and the `.length` is more than 0.
272
273##### .emptyObject(value)
274
275Returns `true` if the value is an `Object` and `Object.keys(value).length` is 0.
276
277Please note that `Object.keys` returns only own enumerable properties. Hence something like this can happen:
278
279```js
280const object1 = {};
281
282Object.defineProperty(object1, 'property1', {
283 value: 42,
284 writable: true,
285 enumerable: false,
286 configurable: true
287});
288
289is.emptyObject(object1);
290//=> true
291```
292
293##### .nonEmptyObject(value)
294
295Returns `true` if the value is an `Object` and `Object.keys(value).length` is more than 0.
296
297##### .emptySet(value)
298
299Returns `true` if the value is a `Set` and the `.size` is 0.
300
301##### .nonEmptySet(Value)
302
303Returns `true` if the value is a `Set` and the `.size` is more than 0.
304
305##### .emptyMap(value)
306
307Returns `true` if the value is a `Map` and the `.size` is 0.
308
309##### .nonEmptyMap(value)
310
311Returns `true` if the value is a `Map` and the `.size` is more than 0.
312
313#### Miscellaneous
314
315##### .directInstanceOf(value, class)
316
317Returns `true` if `value` is a direct instance of `class`.
318
319```js
320is.directInstanceOf(new Error(), Error);
321//=> true
322
323class UnicornError extends Error {}
324
325is.directInstanceOf(new UnicornError(), Error);
326//=> false
327```
328
329##### .urlInstance(value)
330
331Returns `true` if `value` is an instance of the [`URL` class](https://developer.mozilla.org/en-US/docs/Web/API/URL).
332
333```js
334const url = new URL('https://example.com');
335
336is.urlInstance(url);
337//=> true
338```
339
340##### .urlString(value)
341
342Returns `true` if `value` is a URL string.
343
344Note: this only does basic checking using the [`URL` class](https://developer.mozilla.org/en-US/docs/Web/API/URL) constructor.
345
346```js
347const url = 'https://example.com';
348
349is.urlString(url);
350//=> true
351
352is.urlString(new URL(url));
353//=> false
354```
355
356##### .truthy(value)
357
358Returns `true` for all values that evaluate to true in a boolean context:
359
360```js
361is.truthy('🦄');
362//=> true
363
364is.truthy(undefined);
365//=> false
366```
367
368##### .falsy(value)
369
370Returns `true` if `value` is one of: `false`, `0`, `''`, `null`, `undefined`, `NaN`.
371
372##### .nan(value)
373##### .nullOrUndefined(value)
374##### .primitive(value)
375
376JavaScript primitives are as follows: `null`, `undefined`, `string`, `number`, `boolean`, `symbol`.
377
378##### .integer(value)
379
380##### .safeInteger(value)
381
382Returns `true` if `value` is a [safe integer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger).
383
384##### .plainObject(value)
385
386An object is plain if it's created by either `{}`, `new Object()`, or `Object.create(null)`.
387
388##### .iterable(value)
389##### .asyncIterable(value)
390##### .class(value)
391
392Returns `true` for instances created by a class.
393
394**Note:** TypeScript users must use `.class_()` because of a TypeScript naming limitation.
395
396##### .typedArray(value)
397
398##### .arrayLike(value)
399
400A `value` is array-like if it is not a function and has a `value.length` that is a safe integer greater than or equal to 0.
401
402```js
403is.arrayLike(document.forms);
404//=> true
405
406function foo() {
407 is.arrayLike(arguments);
408 //=> true
409}
410foo();
411```
412
413##### .inRange(value, range)
414
415Check if `value` (number) is in the given `range`. The range is an array of two values, lower bound and upper bound, in no specific order.
416
417```js
418is.inRange(3, [0, 5]);
419is.inRange(3, [5, 0]);
420is.inRange(0, [-2, 2]);
421```
422
423##### .inRange(value, upperBound)
424
425Check if `value` (number) is in the range of `0` to `upperBound`.
426
427```js
428is.inRange(3, 10);
429```
430
431##### .domElement(value)
432
433Returns `true` if `value` is a DOM Element.
434
435##### .nodeStream(value)
436
437Returns `true` if `value` is a Node.js [stream](https://nodejs.org/api/stream.html).
438
439```js
440import fs from 'node:fs';
441
442is.nodeStream(fs.createReadStream('unicorn.png'));
443//=> true
444```
445
446##### .observable(value)
447
448Returns `true` if `value` is an `Observable`.
449
450```js
451import {Observable} from 'rxjs';
452
453is.observable(new Observable());
454//=> true
455```
456
457##### .infinite(value)
458
459Check if `value` is `Infinity` or `-Infinity`.
460
461##### .evenInteger(value)
462
463Returns `true` if `value` is an even integer.
464
465##### .oddInteger(value)
466
467Returns `true` if `value` is an odd integer.
468
469##### .propertyKey(value)
470
471Returns `true` if `value` can be used as an object property key (either `string`, `number`, or `symbol`).
472
473##### .formData(value)
474
475Returns `true` if `value` is an instance of the [`FormData` class](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
476
477```js
478const data = new FormData();
479
480is.formData(data);
481//=> true
482```
483
484##### .urlSearchParams(value)
485
486Returns `true` if `value` is an instance of the [`URLSearchParams` class](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams).
487
488```js
489const searchParams = new URLSearchParams();
490
491is.urlSearchParams(searchParams);
492//=> true
493```
494
495##### .any(predicate | predicate[], ...values)
496
497Using a single `predicate` argument, returns `true` if **any** of the input `values` returns true in the `predicate`:
498
499```js
500is.any(is.string, {}, true, '🦄');
501//=> true
502
503is.any(is.boolean, 'unicorns', [], new Map());
504//=> false
505```
506
507Using an array of `predicate[]`, returns `true` if **any** of the input `values` returns true for **any** of the `predicates` provided in an array:
508
509```js
510is.any([is.string, is.number], {}, true, '🦄');
511//=> true
512
513is.any([is.boolean, is.number], 'unicorns', [], new Map());
514//=> false
515```
516
517##### .all(predicate, ...values)
518
519Returns `true` if **all** of the input `values` returns true in the `predicate`:
520
521```js
522is.all(is.object, {}, new Map(), new Set());
523//=> true
524
525is.all(is.string, '🦄', [], 'unicorns');
526//=> false
527```
528
529## Type guards
530
531When using `is` together with TypeScript, [type guards](http://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types) are being used extensively to infer the correct type inside if-else statements.
532
533```ts
534import is from '@sindresorhus/is';
535
536const padLeft = (value: string, padding: string | number) => {
537 if (is.number(padding)) {
538 // `padding` is typed as `number`
539 return Array(padding + 1).join(' ') + value;
540 }
541
542 if (is.string(padding)) {
543 // `padding` is typed as `string`
544 return padding + value;
545 }
546
547 throw new TypeError(`Expected 'padding' to be of type 'string' or 'number', got '${is(padding)}'.`);
548}
549
550padLeft('🦄', 3);
551//=> ' 🦄'
552
553padLeft('🦄', '🌈');
554//=> '🌈🦄'
555```
556
557## Type assertions
558
559The type guards are also available as [type assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions), which throw an error for unexpected types. It is a convenient one-line version of the often repetitive "if-not-expected-type-throw" pattern.
560
561```ts
562import {assert} from '@sindresorhus/is';
563
564const handleMovieRatingApiResponse = (response: unknown) => {
565 assert.plainObject(response);
566 // `response` is now typed as a plain `object` with `unknown` properties.
567
568 assert.number(response.rating);
569 // `response.rating` is now typed as a `number`.
570
571 assert.string(response.title);
572 // `response.title` is now typed as a `string`.
573
574 return `${response.title} (${response.rating * 10})`;
575};
576
577handleMovieRatingApiResponse({rating: 0.87, title: 'The Matrix'});
578//=> 'The Matrix (8.7)'
579
580// This throws an error.
581handleMovieRatingApiResponse({rating: '🦄'});
582```
583
584## Generic type parameters
585
586The type guards and type assertions are aware of [generic type parameters](https://www.typescriptlang.org/docs/handbook/generics.html), such as `Promise<T>` and `Map<Key, Value>`. The default is `unknown` for most cases, since `is` cannot check them at runtime. If the generic type is known at compile-time, either implicitly (inferred) or explicitly (provided), `is` propagates the type so it can be used later.
587
588Use generic type parameters with caution. They are only checked by the TypeScript compiler, and not checked by `is` at runtime. This can lead to unexpected behavior, where the generic type is _assumed_ at compile-time, but actually is something completely different at runtime. It is best to use `unknown` (default) and type-check the value of the generic type parameter at runtime with `is` or `assert`.
589
590```ts
591import {assert} from '@sindresorhus/is';
592
593async function badNumberAssumption(input: unknown) {
594 // Bad assumption about the generic type parameter fools the compile-time type system.
595 assert.promise<number>(input);
596 // `input` is a `Promise` but only assumed to be `Promise<number>`.
597
598 const resolved = await input;
599 // `resolved` is typed as `number` but was not actually checked at runtime.
600
601 // Multiplication will return NaN if the input promise did not actually contain a number.
602 return 2 * resolved;
603}
604
605async function goodNumberAssertion(input: unknown) {
606 assert.promise(input);
607 // `input` is typed as `Promise<unknown>`
608
609 const resolved = await input;
610 // `resolved` is typed as `unknown`
611
612 assert.number(resolved);
613 // `resolved` is typed as `number`
614
615 // Uses runtime checks so only numbers will reach the multiplication.
616 return 2 * resolved;
617}
618
619badNumberAssumption(Promise.resolve('An unexpected string'));
620//=> NaN
621
622// This correctly throws an error because of the unexpected string value.
623goodNumberAssertion(Promise.resolve('An unexpected string'));
624```
625
626## FAQ
627
628### Why yet another type checking module?
629
630There are hundreds of type checking modules on npm, unfortunately, I couldn't find any that fit my needs:
631
632- Includes both type methods and ability to get the type
633- Types of primitives returned as lowercase and object types as camelcase
634- Covers all built-ins
635- Unsurprising behavior
636- Well-maintained
637- Comprehensive test suite
638
639For the ones I found, pick 3 of these.
640
641The most common mistakes I noticed in these modules was using `instanceof` for type checking, forgetting that functions are objects, and omitting `symbol` as a primitive.
642
643### Why not just use `instanceof` instead of this package?
644
645`instanceof` does not work correctly for all types and it does not work across [realms](https://stackoverflow.com/a/49832343/64949). Examples of realms are iframes, windows, web workers, and the `vm` module in Node.js.
646
647## For enterprise
648
649Available as part of the Tidelift Subscription.
650
651The maintainers of @sindresorhus/is and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-sindresorhus-is?utm_source=npm-sindresorhus-is&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
652
653## Related
654
655- [ow](https://github.com/sindresorhus/ow) - Function argument validation for humans
656- [is-stream](https://github.com/sindresorhus/is-stream) - Check if something is a Node.js stream
657- [is-observable](https://github.com/sindresorhus/is-observable) - Check if a value is an Observable
658- [file-type](https://github.com/sindresorhus/file-type) - Detect the file type of a Buffer/Uint8Array
659- [is-ip](https://github.com/sindresorhus/is-ip) - Check if a string is an IP address
660- [is-array-sorted](https://github.com/sindresorhus/is-array-sorted) - Check if an Array is sorted
661- [is-error-constructor](https://github.com/sindresorhus/is-error-constructor) - Check if a value is an error constructor
662- [is-empty-iterable](https://github.com/sindresorhus/is-empty-iterable) - Check if an Iterable is empty
663- [is-blob](https://github.com/sindresorhus/is-blob) - Check if a value is a Blob - File-like object of immutable, raw data
664- [has-emoji](https://github.com/sindresorhus/has-emoji) - Check whether a string has any emoji
665
666## Maintainers
667
668- [Sindre Sorhus](https://github.com/sindresorhus)
669- [Giora Guttsait](https://github.com/gioragutt)
670- [Brandon Smith](https://github.com/brandon93s)