README

# type

## Runtime validation and processing of JavaScript types

- Respects language nature and acknowledges its quirks
- Allows coercion in restricted forms (rejects clearly invalid input, normalizes permissible type deviations)
- No transpilation implied, written to work in all ECMAScript 3+ engines

### Example usage

Bulletproof input arguments normalization and validation:

const ensureString = require('type/string/ensure')
, ensureDate = require('type/date/ensure')
, ensureNaturalNumber = require('type/natural-number/ensure')
, isObject = require('type/object/is');
module.exports = (path, options = { min: 0 }) {
path = ensureString(path, { errorMessage: "%v is not a path" });
if (!isObject(options)) options = {};
const min = ensureNaturalNumber(options.min, { default: 0 })
, max = ensureNaturalNumber(options.max, { isOptional: true })
, startTime = ensureDate(options.startTime, { isOptional: true });
// ...logic
};

### Installation

npm install type

## Utilities

Serves following kind of utilities:

##### `*/coerce`

Restricted coercion into primitive type. Returns coerced value or `null` if value is not coercible per rules.

##### `*/is`

Object type/kind confirmation, returns either `true` or `false`.

##### `*/ensure`

Value validation. Returns input value (in primitive cases possibly coerced) or if value doesn't meet the constraints throws `TypeError` .

Each `*/ensure` utility, accepts following options (eventually passed with second argument):

- `isOptional` - Makes `null` or `undefined` accepted as valid value. In such case instead of `TypeError` being thrown, `null` is returned.
- `default` - A value to be returned if `null` or `undefined` is passed as an input value.
- `errorMessage` - Custom error message (`v` can be used as a placeholder for input value)

### Value

Value, any value that's neither `null` nor `undefined` .

#### <tt>value/is</tt>

Confirms whether passed argument is a value

const isValue = require("type/value/is");
isValue({}); // true
isValue(null); // false

#### <tt>value/ensure</tt>

Ensures if given argument is a value. If it's a value it is returned back, if not `TypeError` is thrown

const ensureValue = require("type/value/ensure");
const obj = {};
ensureValue(obj); // obj
ensureValue(null); // Thrown TypeError: Cannot use null

### Object

Object, any non-primitive value

#### <tt>object/is</tt>

Confirms if passed value is an object

const isObject = require("type/object/is");
isObject({}); // true
isObject(true); // false
isObject(null); // false

#### <tt>object/ensure</tt>

If given argument is an object, it is returned back. Otherwise `TypeError` is thrown.

const ensureObject = require("type/object/ensure");
const obj = {};
ensureObject(obj); // obj
ensureString(null); // Thrown TypeError: null is not an object

### String

string primitive

#### <tt>string/coerce</tt>

Restricted string coercion. Returns string presentation for every value that follows below constraints

- is implicitly coercible to string
- is neither`null` nor `undefined`
- its `toString` method is not `Object.prototype.toString`

For all other values `null` is returned

const coerceToString = require("type/string/coerce");
coerceToString(12); // "12"
coerceToString(undefined); // null

#### <tt>string/ensure</tt>

If given argument is a string coercible value (via `string/coerce`) returns result string. Otherwise `TypeError` is thrown.

const ensureString = require("type/string/ensure");
ensureString(12); // "12"
ensureString(null); // Thrown TypeError: null is not a string

### Number

number primitive

#### <tt>number/coerce</tt>

Restricted number coercion. Returns number presentation for every value that follows below constraints

- is implicitly coercible to number
- is neither `null` nor `undefined`
- is not `NaN` and doesn't coerce to `NaN`

For all other values `null` is returned

const coerceToNumber = require("type/number/coerce");
coerceToNumber("12"); // 12
coerceToNumber({}); // null
coerceToNumber(null); // null

#### <tt>number/ensure</tt>

If given argument is a number coercible value (via `number/coerce`) returns result number. Otherwise `TypeError` is thrown.

const ensureNumber = require("type/number/ensure");
ensureNumber(12); // "12"
ensureNumber(null); // Thrown TypeError: null is not a number

#### Finite Number

Finite number primitive

##### `finite/coerce`

Follows `number/coerce` additionally rejecting `Infinity` and `-Infinity` values (`null` is returned if given values coerces to them)

const coerceToFinite = require("type/finite/coerce");
coerceToFinite("12"); // 12
coerceToFinite(Infinity); // null
coerceToFinite(null); // null

##### `finite/ensure`

If given argument is a finite number coercible value (via `finite/coerce`) returns result number. Otherwise `TypeError` is thrown.

const ensureFinite = require("type/finite/ensure");
ensureFinite(12); // "12"
ensureFinite(null); // Thrown TypeError: null is not a finite number

#### Integer Number

Integer number primitive

##### `integer/coerce`

Follows `finite/coerce` additionally stripping decimal part from the number

const coerceToInteger = require("type/integer/coerce");
coerceToInteger("12.95"); // 12
coerceToInteger(Infinity); // null
coerceToInteger(null); // null

##### `integer/ensure`

If given argument is an integer coercible value (via `integer/coerce`) returns result number. Otherwise `TypeError` is thrown.

const ensureInteger = require("type/integer/ensure");
ensureInteger(12.93); // "12"
ensureInteger(null); // Thrown TypeError: null is not an integer

#### Safe Integer Number

Safe integer number primitive

##### `safe-integer/coerce`

Follows `integer/coerce` but returns `null` in place of values which are beyond `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER` range.

const coerceToSafeInteger = require("type/safe-integer/coerce");
coerceToInteger("12.95"); // 12
coerceToInteger(9007199254740992); // null
coerceToInteger(null); // null

##### `safe-integer/ensure`

If given argument is a safe integer coercible value (via `safe-integer/coerce`) returns result number. Otherwise `TypeError` is thrown.

const ensureSafeInteger = require("type/safe-integer/ensure");
ensureSafeInteger(12.93); // "12"
ensureSafeInteger(9007199254740992); // Thrown TypeError: null is not a safe integer

#### Natural Number

Natural number primitive

##### `natural-number/coerce`

Follows `integer/coerce` but returns `null` for values below `0`

const coerceToNaturalNumber = require("type/natural-number/coerce");
coerceToNaturalNumber("12.95"); // 12
coerceToNaturalNumber(-120); // null
coerceToNaturalNumber(null); // null

##### `natural-number/ensure`

If given argument is a natural number coercible value (via `natural-number/coerce`) returns result number. Otherwise `TypeError` is thrown.

const ensureNaturalNumber = require("type/natural-number/ensure");
ensureNaturalNumber(12.93); // "12"
ensureNaturalNumber(-230); // Thrown TypeError: null is not a natural number

### Plain Object

A plain object

- Inherits directly from `Object.prototype` or `null`
- Is not a constructor's `prototype` property

#### <tt>plain-object/is</tt>

Confirms if given object is a plain object

const isPlainObject = require("type/plain-object/is");
isPlainObject({}); // true
isPlainObject(Object.create(null)); // true
isPlainObject([]); // false

#### <tt>plain-object/ensure</tt>

If given argument is a plain object it is returned back. Otherwise `TypeError` is thrown.

const ensurePlainObject = require("type/plain-object/ensure");
ensurePlainObject({}); // {}
ensureArray("foo"); // Thrown TypeError: foo is not a plain object

### Array

Array instance

#### <tt>array/is</tt>

Confirms if given object is a native array

const isArray = require("type/array/is");
isArray([]); // true
isArray({}); // false
isArray("foo"); // false

#### <tt>array/ensure</tt>

If given argument is an array, it is returned back. Otherwise `TypeError` is thrown.

const ensureArray = require("type/array/ensure");
ensureArray(["foo"]); // ["foo"]
ensureArray("foo"); // Thrown TypeError: foo is not an array

#### Array Like

Array-like value (any value with `length` property)

#### <tt>array-like/is</tt>

Restricted array-like confirmation. Returns true for every value that meets following contraints

- is an object (or with `allowString` option, a string)
- is not a function
- Exposes `length` that meets `array-length` constraints

const isArrayLike = require("type/array-like/is");
isArrayLike([]); // true
isArrayLike({}); // false
isArrayLike({ length: 0 }); // true
isArrayLike("foo"); // false
isArrayLike("foo", { allowString: true }); // true

#### <tt>array-like/ensure</tt>

If given argument is an array-like, it is returned back. Otherwise `TypeError` is thrown.

const ensureArrayLike = require("type/array-like/ensure");
ensureArrayLike({ length: 0 }); // { length: 0 }
ensureArrayLike("foo", { allowString: true }); // "foo"
ensureArrayLike({}); // Thrown TypeError: null is not an iterable

#### Array length

number primitive that conforms as valid array length

##### `array-length/coerce`

Follows `safe-integer/coerce` but returns `null` in place of values which are below `0`

const coerceToArrayLength = require("type/safe-integer/coerce");
coerceToArrayLength("12.95"); // 12
coerceToArrayLength(9007199254740992); // null
coerceToArrayLength(null); // null

##### `array-length/ensure`

If given argument is an array length coercible value (via `array-length/coerce`) returns result number. Otherwise `TypeError` is thrown.

const ensureArrayLength = require("type/array-length/ensure");
ensureArrayLength(12.93); // "12"
ensureArrayLength(9007199254740992); // Thrown TypeError: null is not a valid array length

### Iterable

Value which implements iterable protocol

#### <tt>iterable/is</tt>

Confirms if given object is an iterable and is not a string (unless `allowString` option is passed)

const isIterable = require("type/iterable/is");
isIterable([]); // true
isIterable({}); // false
isIterable("foo"); // false
isIterable("foo", { allowString: true }); // true

Supports also `denyEmpty` option

isIterable([], { denyEmpty: true }); // false
isIterable(["foo"], { denyEmpty: true }); // true

#### <tt>iterable/ensure</tt>

If given argument is an iterable, it is returned back. Otherwise `TypeError` is thrown.

const ensureIterable = require("type/iterable/ensure");
ensureIterable([]); // []
ensureIterable("foo", { allowString: true }); // "foo"
ensureIterable({}); // Thrown TypeError: null is not expected iterable

Additionally items can be coreced with `coerceItem` option. Note that in this case:

- A newly created array with coerced values is returned
- Validation crashes if any of the items is not coercible

ensureIterable(new Set(["foo", 12])); // ["foo", "12"]
ensureIterable(new Set(["foo", {}])); // Thrown TypeError: Set({ "foo", {} }) is not expected iterable

### Date

Date instance

#### <tt>date/is</tt>

Confirms if given object is a native date, and is not an Invalid Date

const isDate = require("type/date/is");
isDate(new Date()); // true
isDate(new Date("Invalid date")); // false
isDate(Date.now()); // false
isDate("foo"); // false

#### <tt>date/ensure</tt>

If given argument is a date object, it is returned back. Otherwise `TypeError` is thrown.

const ensureDate = require("type/date/ensure");
const date = new Date();
ensureDate(date); // date
ensureDate(123123); // Thrown TypeError: 123123 is not a date object

### Time value

number primitive which is a valid time value (as used internally in Date instances)

#### <tt>time-value/coerce</tt>

Follows `integer/coerce` but returns `null` in place of values which go beyond 100 000 0000 days from unix epoch

const coerceToTimeValue = require("type/time-value/coerce");
coerceToTimeValue(12312312); // true
coerceToTimeValue(Number.MAX_SAFE_INTEGER); // false
coerceToTimeValue("foo"); // false

##### `time-value/ensure`

If given argument is a time value coercible value (via `time-value/coerce`) returns result number. Otherwise `TypeError` is thrown.

const ensureTimeValue = require("type/time-value/ensure");
ensureTimeValue(12.93); // "12"
ensureTimeValue(Number.MAX_SAFE_INTEGER); // Thrown TypeError: null is not a natural number

### Function

Function instance

#### <tt>function/is</tt>

Confirms if given object is a native function

const isFunction = require("type/function/is");
isFunction(function () {}); // true
isFunction(() => {}); // true
isFunction(class {}); // true
isFunction("foo"); // false

#### <tt>function/ensure</tt>

If given argument is a function object, it is returned back. Otherwise `TypeError` is thrown.

const ensureFunction = require("type/function/ensure");
const fn = function () {};
ensureFunction(fn); // fn
ensureFunction(/foo/); // Thrown TypeError: /foo/ is not a function

#### Plain Function

A Function instance that is not a Class

##### `plain-function/is`

Confirms if given object is a plain function

const isPlainFunction = require("type/plain-function/is");
isPlainFunction(function () {}); // true
isPlainFunction(() => {}); // true
isPlainFunction(class {}); // false
isPlainFunction("foo"); // false

##### `plain-function/ensure`

If given argument is a plain function object, it is returned back. Otherwise `TypeError` is thrown.

const ensurePlainFunction = require("type/function/ensure");
const fn = function () {};
ensurePlainFunction(fn); // fn
ensurePlainFunction(class {}); // Thrown TypeError: class is not a plain function

### RegExp

RegExp instance

#### <tt>reg-exp/is</tt>

Confirms if given object is a native regular expression object

const isRegExp = require("type/reg-exp/is");
isRegExp(/foo/);
isRegExp({}); // false
isRegExp("foo"); // false

#### <tt>reg-exp/ensure</tt>

If given argument is a regular expression object, it is returned back. Otherwise `TypeError` is thrown.

const ensureRegExp = require("type/reg-exp/ensure");
ensureRegExp(/foo/); // /foo/
ensureRegExp("foo"); // Thrown TypeError: null is not a regular expression object

### Promise

Promise instance

#### <tt>promise/is</tt>

Confirms if given object is a native promise

const isPromise = require("type/promise/is");
isPromise(Promise.resolve()); // true
isPromise({ then: () => {} }); // false
isPromise({}); // false

##### `promise/ensure`

If given argument is a promise, it is returned back. Otherwise `TypeError` is thrown.

const ensurePromise = require("type/promise/ensure");
const promise = Promise.resolve();
ensurePromise(promise); // promise
eensurePromise({}); // Thrown TypeError: [object Object] is not a promise

#### Thenable

Thenable object (an object with `then` method)

##### `thenable/is`

Confirms if given object is a thenable

const isThenable = require("type/thenable/is");
isThenable(Promise.resolve()); // true
isThenable({ then: () => {} }); // true
isThenable({}); // false

##### `thenable/ensure`

If given argument is a thenable object, it is returned back. Otherwise `TypeError` is thrown.

const ensureThenable = require("type/thenable/ensure");
const promise = Promise.resolve();
ensureThenable(promise); // promise
ensureThenable({}); // Thrown TypeError: [object Object] is not a thenable object

### Error

Error instance

#### <tt>error/is</tt>

Confirms if given object is a native error object

const isError = require("type/error/is");
isError(new Error()); // true
isError({ message: "Fake error" }); // false

#### <tt>error/ensure</tt>

If given argument is an error object, it is returned back. Otherwise `TypeError` is thrown.

const ensureError = require("type/error/ensure");
const someError = new Error("Some error");
ensureError(someError); // someError
ensureError({ message: "Fake error" }); // Thrown TypeError: [object Object] is not an error object

### Prototype

Some constructor's `prototype` property

#### <tt>prototype/is</tt>

Confirms if given object serves as a prototype property

const isPrototype = require("type/prototype/is");
isPrototype({}); // false
isPrototype(Object.prototype); // true
isPrototype(Array.prototype); // true

### Tests

    $ npm test