is2 review
is2 2.0.9 is a CommonJS bag of boolean predicates for JavaScript values. It checks primitive tags, containers, numeric relationships, deep equality, host and IP strings, ports, UUIDs, Mongo-like IDs, card-number shapes, and several US contact formats. Every call reduces the answer to `true` or `false`. Our install found a small package with bundled types, yet source inspection shows permissive and dated validation rules that do not belong at a security or payment boundary.
is2 2.0.9 installed in 0.6 seconds and left 4 packages and 1 MB in our sandbox, but its browser detection and several domain validators have source-level traps. Keep it for compatible legacy checks; new input boundaries deserve a focused validator with useful errors.
We installed it
| Install | ✓ · 0.6s | 4 packages on disk · 1 MB |
| Import | ✓ | ESM import works · require() works · CommonJS package |
| Browser | 5.2 KB | gzipped (16.6 KB minified), bundled with esbuild |
| Types | ✓ | TypeScript types bundled |
| Known vulns | 0 | 0 critical · 0 high · 0 moderate · 0 low (npm audit) |
Answers from our run
Does is2 install cleanly?
Yes. In a fresh container with an empty cache, npm install is2 finished in 0.6s, leaving 4 packages and 1 MB on disk. npm audit reported no known vulnerabilities.
How much does is2 add to a browser bundle?
5.2 KB gzipped (16.6 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.
Does is2 work with both ESM and CommonJS?
Yes. Both import 'is2' and require('is2') worked in Node 22 in our run. The package is published as CommonJS.
Does is2 include TypeScript types?
Yes, type declarations ship inside the package, so no @types install is needed.
is2 or is-type-of: which should you use?
is-type-of: Use it for a smaller CommonJS set focused on runtime type identification rather than domain strings. is2 2.0.9 installed in 0.6 seconds and left 4 packages and 1 MB in our sandbox, but its browser detection and several domain validators have source-level traps.
When should you not use is2?
The result controls authentication, payment acceptance, or network access. Card, address, host, UUID, and IP checks use hand-written or permissive rules rather than authoritative parsing.
Use it if
- An existing CommonJS project already depends on is2 aliases and compatibility matters more than replacing familiar predicates.
- Tests need terse boolean checks for numeric relationships, emptiness, deep equality, or membership without assertion output.
- A low-risk Node utility benefits from unrelated checks collected behind one `is` object, and `false` is enough diagnostic detail.
- You deliberately need its legacy tag behavior, including boxed primitives passing the matching primitive predicate.
- The result controls authentication, payment acceptance, or network access. Card, address, host, UUID, and IP checks use hand-written or permissive rules rather than authoritative parsing.
- Code runs in a browser without a `process` shim. `browser()` calls `nodejs()`, which reads the process identifier directly and can throw when that global is absent.
- TypeScript control-flow narrowing matters. The bundled declarations return plain `boolean`, so `is.string(value)` does not narrow an `unknown` value to `string`.
- You expect JavaScript's common number semantics. `is.number(NaN)` returns true, while `is.notANumber('text')` also returns true, and boxed numbers count as numbers.
- Fresh maintenance of changing validation formats is required. Version 2.0.9 was published in September 2022 and the repository's latest push was in December 2022.
Setup reality
We installed is2 2.0.9 in 0.6 seconds in a fresh Node 22 container. npm left 4 packages and 1 MB on disk. is2 itself is 192 KB unpacked, declares 3 direct dependencies and 0 peers, carries an MIT license, and produced 0 audit findings. It bundles TypeScript declarations. Our all-exports browser build measured 16.6 KB minified and 5.2 KB gzipped.
The runtime is CommonJS without an exports map. require('is2') worked on Node 22.23.2, and ESM import also loaded through Node's CommonJS interoperability. TypeScript users should check their compiler settings before assuming a default import. The declarations describe ordinary boolean returns rather than type predicates, so calling a check does not prove a narrower type to the compiler. No credentials, config files, peers, or native compilation are involved.
The hard part is choosing safe predicates. number() uses the object's internal tag and accepts NaN plus boxed values. The UUID expression is not anchored to the whole input. IPv4 logic parses dot-separated segments with parseInt without first proving each segment contains digits only. Personal-address and card-brand helpers encode formats in source and cannot tell whether an account or payment instrument is genuine. Use a dedicated parser or service when a false positive changes access or money.
Version 2.0.9 still advertises Node >=v0.10.0, but that old engine floor is not evidence of current browser behavior. browser() reaches for the global process value before deciding where it runs. All failures collapse to false, including bad shape and unsupported input, so applications must construct their own field-specific errors. The package has had 0 releases since September 2022; pin it when preserving old behavior and test every predicate your code relies on.
Patterns
Load the CommonJS export import-commonjs
const is = require('is2');
console.log(is.version);Version 2.0.9 has no exports map. `require()` worked in our Node 22.23.2 check, while ESM relies on Node's CommonJS interoperability.
Test primitive and container tags check-primitives
is.string('hello'); // true
is.number(42); // true
is.boolean(false); // true
is.array([1, 2]); // true
is.date(new Date()); // trueTag-based checks accept boxed primitives, and `number(NaN)` is true. Pair number checks with `notANumber` when NaN is invalid.
Separate undefined, null, and defined check-nullish
is.defined(value);
is.undefined(value);
is.null(value);
is.nullOrUndefined(value);`defined(null)` returns true because it excludes only `undefined`. Use `nullOrUndefined` when both values represent an absent field.
Recognize synchronous and async functions check-functions
is.function(() => 1); // true
is.syncFunction(() => 1); // true
is.asyncFunction(async () => 1); // true`function()` combines 2 source tag checks for sync and async functions. Generator functions are outside that combined predicate.
Check emptiness for supported values check-empty-values
is.empty([]); // true
is.empty({}); // true
is.empty(''); // true
is.empty(null); // false
is.empty(0); // falseWhitespace is a nonempty string, and the generic helper does not interpret a 0-size Map or Set as empty.
Test integer, decimal, and sign check-number-shape
is.integer(12); // true
is.decimal(12.5); // true
is.positiveInteger(12); // true
is.negativeNumber(-0.5); // true
is.even(12); // trueZero is neither positive nor negative in these predicates. `divisibleBy(0, n)` returns false by implementation choice.
Test inclusive ranges and decimal closeness check-number-range
is.within(7, 1, 10); // true
is.greaterOrEqualTo(7, 7); // true
is.prettyClose(1.234, 1.233, 2); // true`within` includes both endpoints. `prettyClose` compares rounded `toFixed` strings instead of applying an absolute numeric tolerance.
Compare nested arrays and objects compare-deep-values
is.equal(
{ user: { id: 7 }, roles: ['admin'] },
{ user: { id: 7 }, roles: ['admin'] }
); // trueObjects and arrays go through the `deep-is` dependency. A failed comparison returns only `false`, without an assertion diff or mismatch path.
Check a finite set of choices match-enumerated-value
is.matching('draft', 'draft', 'published'); // true
is.enumerator('admin', ['user', 'admin']); // true`matching` compares the first argument to later arguments with strict equality. `enumerator` expects the allowed choices in an array-like value.
Screen host and IP text check-network-address
is.ipv4Address('192.0.2.10');
is.ipv6Address('2001:db8::1');
is.dnsAddress('api.example.com');
is.hostAddress('api.example.com');The IPv4 code uses `parseInt` on each segment without a digits-only precheck. Do not use this result by itself for an access-control rule.
Classify a numeric port check-port
is.port(443); // true
is.systemPort(443); // true: 0 through 1023
is.userPort(8080); // true: 1024 through 65535Ports must be Number values and may include 0. A numeric string such as `'443'` returns false.
Screen UUID and Mongo-like IDs check-identifiers
is.uuid('550e8400-e29b-41d4-a716-446655440000');
is.mongoId('507f1f77bcf86cd799439011');The UUID expression is unanchored, so a longer string can pass by containing a matching substring. Add a full-input check when boundaries matter.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| is-type-of | npm | Use it for a smaller CommonJS set focused on runtime type identification rather than domain strings. |
| type-detect | npm | Use it when one precise type-name function is preferable to dozens of boolean aliases. |
| validator | npm | Use it when email, URL, IP, payment-card, and other string formats are the main concern. |
| ow | npm | Use it when runtime guards should throw specific errors and compose into reusable predicate chains. |
More utils guides
lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

