https://github.com/deno911/dis
Typechecking with ease.
https://github.com/deno911/dis
assertions deno deno-module denoland is javascript type-assertion type-guards type-safety typecheck typeguards typeof typescript utilities
Last synced: 3 months ago
JSON representation
Typechecking with ease.
- Host: GitHub
- URL: https://github.com/deno911/dis
- Owner: deno911
- License: mit
- Created: 2022-08-07T02:38:58.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-06-18T00:16:45.000Z (over 2 years ago)
- Last Synced: 2025-11-20T07:13:54.973Z (3 months ago)
- Topics: assertions, deno, deno-module, denoland, is, javascript, type-assertion, type-guards, type-safety, typecheck, typeguards, typeof, typescript, utilities
- Language: TypeScript
- Homepage: https://deno.land/x/dis
- Size: 140 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
🦕 dis
[](https://deno.land/x/dis)
Originally by [**Sindre Sorhus**](https://github.com/sindresorhus/is) for Node,
ported by [**Nicholas Berlette**](https://github.com/nberlette) for Deno.
---
## Usage
```ts
import * as is from "https://deno.land/x/dis@0.2.0/mod.ts";
```
### Type Checking
```ts
is("🦕");
// 'string'
is(new Map());
// 'Map'
is.number(6);
// true
```
### Assertions
[Assertions](#type-assertions) perform the same type checks, but throw an error
if the type does not match.
```ts
import { assert } from "https://deno.land/x/dis@0.2.0/mod.ts";
assert.string(2);
// => Error: Expected value which is `string`, received value of type `number`.
```
### Assertions with TypeScript
```ts
import { assert } from "https://deno.land/x/dis@0.2.0/mod.ts";
assert.string(foo);
// `foo` is now typed as a `string`.
```
## Highlights
- Written in TypeScript, for Deno and Deno Deploy
- [Extensive use of type guards](#type-guards)
- [Supports type assertions](#type-assertions)
- [Aware of generic type parameters](#generic-type-parameters) (use with
caution)
- Actively maintained
---
# API
## is(value)
Attempts to ascertain the type of the value it receives. Accepts only one
argument.
```ts
is("🦕");
// 'string'
is(new Map());
// 'Map'
```
> **Returns**: the type of `value`.
## `is.{method}`
All the below methods accept a value and returns a boolean for whether the value
is of the desired type.
```ts
is.number(6);
// true
is.undefined(true);
// false
```
---
## Primitives
> **Note**: Primitives are **lowercase** and object types are **camelCase**.
Examples of Primitives
---
- `'undefined'`
- `'null'`
- `'string'`
- `'symbol'`
- `'Array'`
- `'Function'`
- `'Object'`
> **Note**: It will throw an error if you try to feed it object-wrapped
> primitives, as that's a bad practice (e.g. `new String('foo')`)
API Methods
---
### undefined
```ts
is.undefined(value);
```
### null
```ts
is.null(value);
```
> **Note**: TypeScript users must use `.null_()` because of a TypeScript naming
> limitation.
### string
```ts
is.string(value);
```
### number
```ts
is.number(value);
```
> **Note:** `is.number(NaN)` returns `false`. This intentionally deviates from
> `typeof` behavior to increase user-friendliness of `is` type checks.
### boolean
```ts
is.boolean(value);
```
### symbol
```ts
is.symbol(value);
```
### bigint
```ts
is.bigint(value);
```
---
## Builtins
API Methods
---
### array
```ts
is.array(value, assertion?)
```
> **Returns**: true if `value` is an array and all of its items match the
> assertion (if provided).
#### Examples
```ts
is.array(value); // Validate `value` is an array.
is.array(value, is.number); // Validate `value` is an array and all of its items are numbers.
```
### function
```ts
is.function(value);
```
> **Note**: TypeScript users must use `.function_()` because of a TypeScript
> naming limitation.
### buffer
```ts
is.buffer(value);
```
### blob
```ts
is.blob(value);
```
### object
```ts
is.object(value);
```
> **Important**: Keep in mind that
> [functions are objects too](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions).
### numericString
```ts
is.numericString(value);
```
> **Returns**: `true` for a string that represents a number satisfying
> `is.number`, for example, `'42'` and `'-8.3'`.
> **Important**: `'NaN'` returns `false`, but `'Infinity'` and `'-Infinity'`
> return `true`.
### regExp
```ts
is.regExp(value);
```
### date
```ts
is.date(value);
```
### error
```ts
is.error(value);
```
### nativePromise
```ts
is.nativePromise(value);
```
### promise
```ts
is.promise(value);
```
> **Returns**: `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.
### generator
```ts
is.generator(value);
```
> **Returns**: `true` for any object that implements its own `.next()` and
> `.throw()` methods and has a function definition for `Symbol.iterator`.
### generatorFunction
```ts
is.generatorFunction(value);
```
### asyncFunction
```ts
is.asyncFunction(value);
```
> **Returns**: `true` for any `async` function that can be called with the
> `await` operator.
#### Examples
```ts
is.asyncFunction(async () => {});
// true
is.asyncFunction(() => {});
// false
```
### asyncGenerator
```ts
is.asyncGenerator(value);
```
#### Examples
```ts
is.asyncGenerator(
(async function* () {
yield 4;
})(),
);
// true
is.asyncGenerator(
(function* () {
yield 4;
})(),
);
// false
```
### asyncGeneratorFunction
```ts
is.asyncGeneratorFunction(value);
```
#### Examples
```ts
is.asyncGeneratorFunction(async function* () {
yield 4;
});
// true
is.asyncGeneratorFunction(function* () {
yield 4;
});
// false
```
### boundFunction
```ts
is.boundFunction(value);
```
> **Returns**: `true` for any `bound` function.
```ts
is.boundFunction(() => {});
// true
is.boundFunction(function () {}.bind(null));
// true
is.boundFunction(function () {});
// false
```
### map
```ts
is.map(value);
```
### set
```ts
is.set(value);
```
### weakMap
```ts
is.weakMap(value);
```
### weakSet
```ts
is.weakSet(value);
```
### weakRef
```ts
is.weakRef(value);
```
---
## TypedArrays
API Methods
---
### int8Array
```ts
is.int8Array(value);
```
### uint8Array
```ts
is.uint8Array(value);
```
### uint8ClampedArray
```ts
is.uint8ClampedArray(value);
```
### int16Array
```ts
is.int16Array(value);
```
### uint16Array
```ts
is.uint16Array(value);
```
### int32Array
```ts
is.int32Array(value);
```
### uint32Array
```ts
is.uint32Array(value);
```
### float32Array
```ts
is.float32Array(value);
```
### float64Array
```ts
is.float64Array(value);
```
### bigInt64Array
```ts
is.bigInt64Array(value);
```
### bigUint64Array
```ts
is.bigUint64Array(value);
```
---
## Structured Data
API Methods
---
### arrayBuffer
```ts
is.arrayBuffer(value);
```
### sharedArrayBuffer
```ts
is.sharedArrayBuffer(value);
```
### dataView
```ts
is.dataView(value);
```
### enumCase
```ts
is.enumCase(value, enum)
```
> **Note**: **TypeScript-only**. Returns `true` if `value` is a member of
> `enum`.
```ts
enum Direction {
Ascending = "ascending",
Descending = "descending",
}
is.enumCase("ascending", Direction);
// true
is.enumCase("other", Direction);
// false
```
---
## Emptiness
API Methods
---
### emptyString
```ts
is.emptyString(value);
```
> **Returns**: `true` if the value is a `string` and the `.length` is 0.
### emptyStringOrWhitespace
```ts
is.emptyStringOrWhitespace(value);
```
> **Returns**: `true` if `is.emptyString(value)` or if it's a `string` that is
> all whitespace.
### nonEmptyString
```ts
is.nonEmptyString(value);
```
> **Returns**: `true` if the value is a `string` and the `.length` is more
> than 0.
### nonEmptyStringAndNotWhitespace
```ts
is.nonEmptyStringAndNotWhitespace(value);
```
> **Returns**: `true` if the value is a `string` that is not empty and not
> whitespace.
```ts
const values = ["property1", "", null, "property2", " ", undefined];
values.filter(is.nonEmptyStringAndNotWhitespace);
// ['property1', 'property2']
```
### emptyArray
```ts
is.emptyArray(value);
```
> **Returns**: `true` if the value is an `Array` and the `.length` is 0.
### nonEmptyArray
```ts
is.nonEmptyArray(value);
```
> **Returns**: `true` if the value is an `Array` and the `.length` is more
> than 0.
### emptyObject
```ts
is.emptyObject(value);
```
> **Returns**: `true` if the value is an `Object` and
> `Object.keys(value).length` is 0.
> **Note**: `Object.keys` returns only own enumerable properties. Hence
> something like this can happen:
```ts
const object1 = {};
Object.defineProperty(object1, "property1", {
value: 42,
writable: true,
enumerable: false,
configurable: true,
});
is.emptyObject(object1);
// true
```
### nonEmptyObject
```ts
is.nonEmptyObject(value);
```
> **Returns**: `true` if the value is an `Object` and
> `Object.keys(value).length` is more than 0.
### emptySet
```ts
is.emptySet(value);
```
> **Returns**: `true` if the value is a `Set` and the `.size` is 0.
### nonEmptySet
```ts
is.nonEmptySet(Value);
```
> **Returns**: `true` if the value is a `Set` and the `.size` is more than 0.
### emptyMap
```ts
is.emptyMap(value);
```
> **Returns**: `true` if the value is a `Map` and the `.size` is 0.
### nonEmptyMap
```ts
is.nonEmptyMap(value);
```
> **Returns**: `true` if the value is a `Map` and the `.size` is more than 0.
---
## Everything Else
API Methods
---
### directInstanceOf
```ts
is.directInstanceOf(value, class)
```
> **Returns**: `true` if `value` is a direct instance of `class`.
```ts
is.directInstanceOf(new Error(), Error);
// true
class UnicornError extends Error {}
is.directInstanceOf(new UnicornError(), Error);
// false
```
### urlInstance
```ts
is.urlInstance(value);
```
> **Returns**: `true` if `value` is an instance of the
> [`URL` class](https://mdn.io/URL).
```ts
const url = new URL("https://example.com");
is.urlInstance(url);
// true
```
### urlString
```ts
is.urlString(value);
```
> **Returns**: `true` if `value` is a URL string.
Note: this only does basic checking using the [`URL` class](https://mdn.io/URL)
constructor.
```ts
const url = "https://example.com";
is.urlString(url);
// true
is.urlString(new URL(url));
// false
```
### truthy
```ts
is.truthy(value);
```
> **Returns**: `true` for all values that evaluate to true in a boolean context:
```ts
is.truthy("🦕");
// true
is.truthy(undefined);
// false
```
### falsy
```ts
is.falsy(value);
```
> **Returns**: `true` if `value` is one of: `false`, `0`, `''`, `null`,
> `undefined`, `NaN`.
### NaN
```ts
is.nan(value);
```
### nullOrUndefined
```ts
is.nullOrUndefined(value);
```
### primitive
```ts
is.primitive(value);
```
JavaScript primitives are as follows: `null`, `undefined`, `string`, `number`,
`boolean`, `symbol`.
### integer
```ts
is.integer(value);
```
### safeInteger
```ts
is.safeInteger(value);
```
> **Returns**: `true` if `value` is a
> [safe integer](https://mdn.io/isSafeInteger).
### plainObject
```ts
is.plainObject(value);
```
An object is plain if it's created by either `{}`, `new Object()`, or
`Object.create(null)`.
### iterable
```ts
is.iterable(value);
```
### asyncIterable
```ts
is.asyncIterable(value);
```
### class
```ts
is.class(value);
```
> **Returns**: `true` for instances created by a class.
**Note:** TypeScript users must use `.class_()` because of a TypeScript naming
limitation.
### typedArray
```ts
is.typedArray(value);
```
### arrayLike
```ts
is.arrayLike(value);
```
A `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.
```ts
is.arrayLike(document.forms);
// true
function foo() {
is.arrayLike(arguments);
// true
}
foo();
```
### inRange
```ts
is.inRange(value, range);
```
Check 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.
```ts
is.inRange(3, [0, 5]);
is.inRange(3, [5, 0]);
is.inRange(0, [-2, 2]);
```
### inRange
```ts
is.inRange(value, upperBound);
```
Check if `value` (number) is in the range of `0` to `upperBound`.
```ts
is.inRange(3, 10);
```
### domElement
```ts
is.domElement(value);
```
> **Returns**: `true` if `value` is a DOM Element.
### nodeStream
```ts
is.nodeStream(value);
```
> **Returns**: `true` if `value` is a Node.js
> [stream](https://nodejs.org/api/stream.html).
```ts
import fs from "node:fs";
is.nodeStream(fs.createReadStream("unicorn.png"));
// true
```
### observable
```ts
is.observable(value);
```
> **Returns**: `true` if `value` is an `Observable`.
```ts
import { Observable } from "rxjs";
is.observable(new Observable());
// true
```
### infinite
```ts
is.infinite(value);
```
Check if `value` is `Infinity` or `-Infinity`.
### evenInteger
```ts
is.evenInteger(value);
```
> **Returns**: `true` if `value` is an even integer.
### oddInteger
```ts
is.oddInteger(value);
```
> **Returns**: `true` if `value` is an odd integer.
### propertyKey
```ts
is.propertyKey(value);
```
> **Returns**: `true` if `value` can be used as an object property key (either
> `string`, `number`, or `symbol`).
### formData
```ts
is.formData(value);
```
> **Returns**: `true` if `value` is an instance of the
> [`FormData` class](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
```ts
const data = new FormData();
is.formData(data);
// true
```
### urlSearchParams
```ts
is.urlSearchParams(value);
```
> **Returns**: `true` if `value` is an instance of the
> [`URLSearchParams` class](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams).
```ts
const searchParams = new URLSearchParams();
is.urlSearchParams(searchParams);
// true
```
### any
```ts
is.any(predicate | predicate[], ...values)
```
Using a single `predicate` argument, returns `true` if **any** of the input
`values` returns true in the `predicate`:
```ts
is.any(is.string, {}, true, "🦕");
// true
is.any(is.boolean, "denosaurs", [], new Map());
// false
```
Using an array of `predicate[]`, returns `true` if **any** of the input `values`
returns true for **any** of the `predicates` provided in an array:
```ts
is.any([is.string, is.number], {}, true, "🦕");
// true
is.any([is.boolean, is.number], "denosaurs", [], new Map());
// false
```
### all
```ts
is.all(predicate, ...values);
```
> **Returns**: `true` if **all** of the input `values` returns true in the
> `predicate`:
```ts
is.all(is.object, {}, new Map(), new Set());
// true
is.all(is.string, "🦕", [], "denosaurs");
// false
```
---
## Type Guards
When 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.
Examples
---
```ts
import is from "https://deno.land/x/dis@0.2.0/mod.ts";
const padLeft = (value: string, padding: string | number) => {
if (is.number(padding)) {
// `padding` is typed as `number`
return Array(padding + 1).join(" ") + value;
}
if (is.string(padding)) {
// `padding` is typed as `string`
return padding + value;
}
throw new TypeError(
`Expected 'padding' to be of type 'string' or 'number', got '${
is(padding)
}'.`,
);
};
padLeft("🦕", 3);
// ' 🦕'
padLeft("🦕", "🌈");
// '🌈🦕'
```
---
## Type Assertions
The 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.
Examples
---
```ts
import { assert } from "https://deno.land/x/dis@0.2.0/mod.ts";
const handleMovieRatingApiResponse = (response: unknown) => {
assert.plainObject(response);
// `response` is now typed as a plain `object` with `unknown` properties.
assert.number(response.rating);
// `response.rating` is now typed as a `number`.
assert.string(response.title);
// `response.title` is now typed as a `string`.
return `${response.title} (${response.rating * 10})`;
};
handleMovieRatingApiResponse({ rating: 0.87, title: "The Matrix" });
// 'The Matrix (8.7)'
// This throws an error.
handleMovieRatingApiResponse({ rating: "🦕" });
```
---
## Generic type parameters
More Information
---
---
The type guards and type assertions are aware of
[generic type parameters](https://www.typescriptlang.org/docs/handbook/generics.html),
such as `Promise` and `Map`. 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.
Use 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`.
Examples
---
```ts
import { assert } from "https://deno.land/x/dis@0.2.0/mod.ts";
async function badNumberAssumption(input: unknown) {
// Bad assumption about the generic type parameter fools the compile-time type system.
assert.promise(input);
// `input` is a `Promise` but only assumed to be `Promise`.
const resolved = await input;
// `resolved` is typed as `number` but was not actually checked at runtime.
// Multiplication will return NaN if the input promise did not actually contain a number.
return 2 * resolved;
}
async function goodNumberAssertion(input: unknown) {
assert.promise(input);
// `input` is typed as `Promise`
const resolved = await input;
// `resolved` is typed as `unknown`
assert.number(resolved);
// `resolved` is typed as `number`
// Uses runtime checks so only numbers will reach the multiplication.
return 2 * resolved;
}
badNumberAssumption(Promise.resolve("An unexpected string"));
// NaN
// This correctly throws an error because of the unexpected string value.
goodNumberAssertion(Promise.resolve("An unexpected string"));
```
---
## Frequently Asked Questions
Why yet another type checking module?
---
There are hundreds of type checking modules on npm, unfortunately, I couldn't
find any that fit my needs:
- Includes both type methods and ability to get the type
- Types of primitives returned as lowercase and object types as camelcase
- Covers all built-ins
- Unsurprising behavior
- Well-maintained
- Comprehensive test suite
For the ones I found, pick 3 of these.
The 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.
Why not just use `instanceof` instead of this package?
---
`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.
---
**MIT License**. Originally by
[**Sindre Sorhus**](https://github.com/sindresorhus/is). Ported by
[**Nicholas Berlette**](https://github.com/nberlette) for Deno.