A light wrapper around the amazing is type-checking library by Sindre Sorhus designed to throw nice error messages when type assertions fail. You should familiarize yourself with is before using this library.
Install
$ npm i @darkobits/assert-is
Use
assertIs(methodOrMethods: string | array, valueOrQualifier: any, value: ?any) : any
assertIs accepts a string (identifying a method from is) and a value to test. If is returns true, the value is returned. If it returns false, an error is thrown.
import assertIs from '@darkobits/assert-is'; function add (a, b) { assertIs('number', a); assertIs('number', b); return a + b; } add(2, 2) //=> 4 add(2, 'two') //=> TypeError('Expected value to be of type "number", got "string".') // assertIs returns the provided value on success, so we can even get fancy: const add = (a, b) => assertIs('number', a) + assertIs('number', b);
Qualifiers
Some is methods require an additional parameter. For example, inRange accepts a range ([min: number, max: number] or max: number) in addition to the value to check. When using these methods with assertIs, the qualifier always precedes the value.
import assertIs from '@darkobits/assert-is'; // Assert that a number is positive: assertIs('inRange', [1, Infinity], 42); //=> 42 assertIs('inRange', [1, Infinity], NaN); //=> RangeError('Expected value NaN to be between 1 and Infinity.')
Union Types
assertIs can be used to check if a value satisfies at least one of several is predicates.
Note: Predicates which require qualifiers (like inRange and directInstanceOf) are not supported when performing union type assertions.
import assertIs from '@darkobits/assert-is'; function greet (name, age) { assertIs('string', name); assertIs(['string', 'number'], age); return `Hello! My name is ${name}, and I am ${age} years old.`; } greet('Bob', 36) //=> 'Hello! My name is Bob, and I am 36 years old.' greet('Alice', 'forty-three') //=> 'Hello! My name is Alice, and I am forty-three years old.' greet('Leeroy', NaN) //=> TypeError('Expected type of value to be either "string" or "number". Got "NaN".')
Currying
When assertIs receives fewer arguments than it needs to perform an assertion, it returns a function which accepts the remaining arguments. This allows for the creation of custom, re-usable assertion functions:
import assertIs from '@darkobits/assert-is'; const assertIsString = assertIs('string'); assertIsString({}); //=> TypeError('Expected value to be of type "string", got "object".') const assertIsLessThanFive = assertIs('inRange', 5); const assertIsLessThanFive(10); //=> RangeError('Expected value 10 to be less than 5.') class Person { } const assertIsPerson = assertIs('instanceOf', Person); assertIsPerson(new Person()); //=> Person assertIsPerson({}); //=> TypeError('Expected value to be an instance of "Person".') const assertIsIterable = assertIs(['array', 'map', 'set', 'weakMap', 'weakSet']); assertIsIterable([1, 2, 3]); //=> [1, 2, 3] assertIsIterable(function () {}); //=> TypeError('Expected type of value to be either "Array", "Map", "WeakMap" or "WeakSet". Got "Function".')
Additional Assertions
In addition to the methods provided by is, assertIs also provides the following assertions:
instanceOf(Ctor: class | function, instance: any)
Expects a constructor and an object and asserts that the object is an instance of the constructor/class.
import assertIs from '@darkobits/assert-is'; class Person { } const myPerson = new Person(); assertIs('instanceOf', Person, myPerson); //=> myPerson assertIs('instanceOf', Person, 'foo'); //=> TypeError('Expected value to be an instance of "Person", got "string".')
subclassOf(SuperclassCtor: class | function, SubclassCtor: class | function)
Expects two constructors and asserts that the second is a subclass of (re: extends) the first.
import assertIs from '@darkobits/assert-is'; class Person { } class Teacher extends Person { } assertIs('subclassOf', Person, Teacher); //=> Teacher class Animal { } assertIs('subclassOf', Person, Animal); //=> TypeError('Expected value to be a subclass of "Person".')
Contexts
assertIs provides a fluent API for adding additional contextual information to errors:
import assertIs from '@darkobits/assert-is'; // or: import { context } from '@darkobits/assert-is'; function add (a, b) { const assert = assertIs.context('add'); // or: const assert = context('add'); // Use assert() just like assertIs(): assert('number', a); // This will throw errors like: // TypeError('[add] Expected value to be of type "number", got...'); // Or, use the 'arg' + 'is' methods to provide additional context about an assertion: assert.arg('first argument', a).is('number'); // This will throw errors like: // TypeError('[add] Expected first argument to be of type "number", got...'); // You can also chain arg/is calls: assert.arg('first argument', a).is('number').arg('second argument', b).is('number'); return a + b; }
The signatures for these methods are:
arg(label: string, value: any) : function
You may also use label (an alias to arg) if you prefer. This method always returns an object with is(), which accepts the type or types you expect.
is(typeOrTypes: string | array): AssertionContext
This method always returns the assertion context, meaning you can chain arg + is calls.