@pwn/is
Version:
Minimalistic predicate library
723 lines (538 loc) • 20.1 kB
Markdown
# is.js



Minimalistic predicate library.
> This is a general purpose check library, you may found [tagOf](https://github.com/pwnn/tagOf) useful if all you want is just check types.
## Install
Node:
```sh
$ npm install --save /is
```
Browser:
```html
<script src="path/to/is.min.js"></script>
```
## Features
- Zero dependencies.
- Un-opinionated — includes only the bare minimum predicates you're likely to use.
- Works with Node, AMD and all browsers, including IE6.
- Extensible.
## Usage
A code sample is worth a thousand words:
```js
const is = require( '/is' )
is.array( [] ) // true
is.not.integer( 0 ) // false
is.propertyDefined( { foo : { bar : 0 } } , 'foo.bar' ) // true
is.equal( [ 1 , [ 2 , 3 ] ] , [ 1 , [ 2 , 3 ] ] ) // false
is.deepEqual( [ 1 , [ 2 , 3 ] ] , [ 1 , [ 2 , 3 ] ] ) // true
// use a third-party bundle
is.use( require( 'path/to/some/math/bundle' ) )
is.prime( 7 ) // true
```
All checks, or _predicates_ in `is.js` terminology, takes two general forms:
- __POSITIVE CHECK__: `is.predicate( ...args )` - Checks whether certain condition met.
- __NEGATIVE CHECK__: `is.not.predicate( ...args )` - The inverse of its corresponding positive check.
That's it! What's next?
- [Cheatsheet](#cheatsheet) - List of available predicates shipped with `is.js`.
- [API reference](#api-reference) - Detailed documentation on each predicate.
- [Writing new predicates](#writing-new-predicates) - Learn how to define new predicates.
## Cheatsheet
TL;DR
> A _bundle_ is simply a way of organizing related predicates.
__bundle:nil__
- [is.null( value )](#isnull-value-)
- [is.undefined( value )](#isundefined-value-)
- [is.exist( value )](#isexist-value-)
- [is.nil( value )](#isnil-value-)
__bundle:number__
- [is.number( value )](#isnumber-value-)
- [is.numeral( value )](#isnumeral-value-)
- [is.nan( value )](#isnan-value-)
- [is.odd( number )](#isodd-number-)
- [is.even( number )](#iseven-number-)
- [is.finite( number )](#isfinite-number-)
- [is.infinite( number )](#isinfinite-number-)
- [is.integer( number )](#isinteger-number-)
- [is.safeInteger( number )](#issafeinteger-number-)
__bundle:string__
- [is.string( value )](#isstring-value-)
- [is.emptyString( string )](#isemptystring-string-)
- [is.substring( substring , string , [offset=0] )](#issubstring-substring--string--offset0-)
- [is.prefix( prefix , string )](#isprefix-prefix--string-)
- [is.suffix( suffix , string )](#issuffix-suffix--string-)
__bundle:boolean__
- [is.boolean( value )](#isboolean-value-)
__bundle:object__
- [is.object( value )](#isobject-value-)
- [is.emptyObject( object )](#isemptyobject-object-)
- [is.propertyDefined( object , path )](#ispropertydefined-object--path-)
- [is.conforms( object , schema , [strict=false] )](#isconforms-object--schema--strictfalse-)
__bundle:array__
- [is.array( value )](#isarray-value-)
- [is.arrayLikeObject( value )](#isarraylikeobject-value-)
- [is.inArray( value , array , [offset=0] , [comparator=is.equal] )](#isinarray-value--array--offset0--comparatorisequal-)
__bundle:type__
- [is.sameType( value , other )](#issametype-value--other-)
- [is.primitive( value )](#isprimitive-value-)
- [is.date( value )](#isdate-value-)
- [is.error( value )](#iserror-value-)
- [is.function( value )](#isfunction-value-)
- [is.map( value )](#ismap-value-)
- [is.regexp( value )](#isregexp-value-)
- [is.set( value )](#isset-value-)
- [is.symbol( value )](#issymbol-value-)
__bundle:equality__
- [is.equal( value , other )](#isequal-value--other-)
- [is.deepEqual( value , other )](#isdeepequal-value--other-)
## API reference
#### is.null( value )
Checks whether given value is `null`.
```js
is.null( null ) // true
is.null( undefined ) // false
```
#### is.undefined( value )
Checks whether given value is `undefined`.
```js
is.undefined( null ) // false
is.undefined( undefined ) // true
```
#### is.exist( value )
Checks whether given value exists, i.e, not `null` nor `undefined`.
```js
is.exist( null ) // false
is.exist( undefined ) // false
```
#### is.nil( value )
Checks whether given value is either `null` or `undefined`.
```js
is.nil( null ) // true
is.nil( undefined ) // true
```
#### is.number( value )
Checks whether given value is a number.
```js
is.number( 0 ) // true
is.number( Number.NaN ) // true
is.number( Number.POSITIVE_INFINITY ) // true
is.number( Number.NEGATIVE_INFINITY ) // true
is.number( '0' ) // false
is.number( new Number( 0 ) ) // false
```
#### is.numeral( value )
Checks whether given value is a numeral, i.e:
- a genuine finite number
- or a string that represents a finite number
```js
is.numeral( null ) // false
is.numeral( undefined ) // false
is.numeral( true ) // false
is.numeral( false ) // false
is.numeral( Symbol( 0 ) ) // false
is.numeral( Symbol.for( 0 ) ) // false
is.numeral( { valueOf() { return 0 } } ) // false
is.numeral( [ 0 ] ) // false
is.numeral( () => 0 ) // false
is.numeral( '' ) // false
is.numeral( 'one' ) // false
is.numeral( '1px' ) // false
is.numeral( ' 0xFF ' ) // true
is.numeral( '1e1' ) // true
is.numeral( '1.1E-1' ) // true
is.numeral( '-1' ) // true
is.numeral( '1.1' ) // true
is.numeral( new Number( 1 ) ) // true
is.numeral( new String( '-1.1' ) ) // true
is.numeral( Number.NaN ) // false
is.numeral( Number.POSITIVE_INFINITY ) // false
is.numeral( Number.NEGATIVE_INFINITY ) // false
```
#### is.nan( value )
Checks whether given value is `NaN`.
```js
is.nan( 0 ) // false
is.nan( Number.NaN ) // true
is.nan( new Number( Number.NaN ) ) // false
is.nan( Number.POSITIVE_INFINITY ) // false
is.nan( Number.NEGATIVE_INFINITY ) // false
is.nan( 'one' ) // false
```
#### is.odd( number )
Checks whether given value is an odd number.
```js
is.odd( 1 ) // true
is.odd( 2 ) // false
is.odd( '1' ) // false
is.odd( '2' ) // false
is.odd( new Number( 1 ) ) // false
is.odd( new Number( 2 ) ) // false
is.odd( Number.NaN ) // false
is.odd( Number.POSITIVE_INFINITY ) // false
is.odd( Number.NEGATIVE_INFINITY ) // false
```
#### is.even( number )
Checks whether given value is an even number.
```js
is.even( 1 ) // false
is.even( 2 ) // true
is.even( '1' ) // false
is.even( '2' ) // false
is.even( new Number( 1 ) ) // false
is.even( new Number( 2 ) ) // false
is.even( Number.NaN ) // false
is.even( Number.POSITIVE_INFINITY ) // false
is.even( Number.NEGATIVE_INFINITY ) // false
```
#### is.finite( number )
Checks whether given value is a finite number.
```js
is.finite( 0 ) // true
is.finite( '0' ) // false
is.finite( Number.NaN ) // false
is.finite( Number.POSITIVE_INFINITY ) // false
is.finite( Number.NEGATIVE_INFINITY ) // false
```
#### is.infinite( number )
Checks whether given value is an infinite number, i.e,
`Number.POSITIVE_INFINITY` or `Number.NEGATIVE_INFINITY`.
```js
is.infinite( 0 ) // false
is.infinite( '0' ) // false
is.infinite( Number.NaN ) // false
is.infinite( Number.POSITIVE_INFINITY ) // true
is.infinite( Number.NEGATIVE_INFINITY ) // true
```
#### is.integer( number )
Checks whether given value is an integer.
```js
is.integer( 0 ) // true
is.integer( '0' ) // false
is.integer( new Number( 0 ) ) // false
is.integer( 0.1 ) // false
is.integer( Number.NaN ) // false
is.integer( Number.POSITIVE_INFINITY ) // false
is.integer( Number.NEGATIVE_INFINITY ) // false
is.integer( Number.MAX_SAFE_INTEGER ) // true
is.integer( Number.MIN_SAFE_INTEGER ) // true
is.integer( Number.MAX_SAFE_INTEGER + 1 ) // true
is.integer( Number.MIN_SAFE_INTEGER - 1 ) // true
```
#### is.safeInteger( number )
Checks whether given value is a safe integer.
```js
is.safeInteger( 0 ) // true
is.safeInteger( '0' ) // false
is.safeInteger( new Number( 0 ) ) // false
is.safeInteger( 0.1 ) // false
is.safeInteger( Number.NaN ) // false
is.safeInteger( Number.POSITIVE_INFINITY ) // false
is.safeInteger( Number.NEGATIVE_INFINITY ) // false
is.safeInteger( Number.MAX_SAFE_INTEGER ) // true
is.safeInteger( Number.MIN_SAFE_INTEGER ) // true
is.safeInteger( Number.MAX_SAFE_INTEGER + 1 ) // false
is.safeInteger( Number.MIN_SAFE_INTEGER - 1 ) // false
```
#### is.string( value )
Checks whether given value is a string.
```js
is.string( 'lipsum' ) // true
is.string( new String( 'lipsum' ) ) // false
```
#### is.emptyString( string )
Checks whether given value is an empty string, i.e, a string with whitespace characters only.
```js
is.emptyString( '' ) // true
is.emptyString( ' ' ) // true
is.emptyString( '\f\n\r\t' ) // true
is.emptyString( '\u0009\u000A\u000B\u000C\u000D\u0020' ) // true
is.emptyString( 'lipsum' ) // false
```
#### is.substring( substring , string , [offset=0] )
Checks whether one string may be found within another string.
```js
is.substring( 'ps' , 'lipsum' ) // true
is.substring( 'sp' , 'lipsum' ) // false
is.substring( [ 'ps' ] , 'lipsum' ) // true; `substring` will be converted to a string as needed
is.substring( 'ps' , [ 'lipsum' ] ) // false; `string` must be a string
is.substring( 'ps' , 'lipsum' , 2 ) // true
is.substring( 'ps' , 'lipsum' , 3 ) // false
is.substring( 'ps' , 'lipsum' , 3.14 ) // true; non-integer offset will be omitted and defaults to 0
is.substring( 'ps' , 'lipsum' , -4 ) // true; supports negative offset
is.substring( 'ps' , 'lipsum' , 6 ) // false; offset out of range
is.substring( 'ps' , 'lipsum' , -7 ) // false; offset out of range
```
#### is.prefix( prefix , string )
Checks whether `string` starts with `prefix`.
```js
is.prefix( 'lip' , 'lipsum' ) // true
is.prefix( 'sum' , 'lipsum' ) // false
is.prefix( 'lip' , [ 'lipsum' ] ) // false; `string` must be a string
is.prefix( [ 'lip' ] , 'lipsum' ) // true - `prefix` will be converted to a string as needed
```
#### is.suffix( suffix , string )
Checks whether `string` ends with `suffix`.
```js
is.suffix( 'sum' , 'lipsum' ) // true
is.suffix( 'lip' , 'lipsum' ) // false
is.suffix( 'sum' , [ 'lipsum' ] ) // false; `string` must be a string
is.suffix( [ 'sum' ] , 'lipsum' ) // true - `suffix` will be converted to a string as needed
```
#### is.boolean( value )
Checks whether given value is a boolean.
```js
is.boolean( 1 ) // false
is.boolean( 0 ) // false
is.boolean( true ) // true
is.boolean( false ) // true
is.boolean( new Boolean( true ) ) // false
is.boolean( new Boolean( false ) ) // false
```
#### is.object( value )
Checks whether given value is an object.
```js
is.object( null ) // false
is.object( undefined ) // false
is.object( 0 ) // false
is.object( new Number( 0 ) ) // true
is.object( '' ) // false
is.object( new String( '' ) ) // true
is.object( true ) // false
is.object( new Boolean( true ) ) // true
is.object( Symbol() ) // false
is.object( Symbol.for( 'is' ) ) // false
is.object( {} ) // true
is.object( [] ) // true
is.object( function () {} ) // true
```
#### is.emptyObject( object )
Checks whether given value is an empty object, i.e, an object without any own, enumerable, string keyed properties.
```js
is.emptyObject( {} ) // true
is.emptyObject( { foo : 'bar' } ) // false
is.emptyObject( Object.create( { foo : 'bar' } ) ) // true; ignore inherited properties
is.emptyObject( Object.defineProperty( {} , 'foo' , { value : 'bar' } ) ) // true; ignore non-enumerable properties
is.emptyObject( { [ Symbol() ] : 0 } ) // true; ignore non-string-keyed properties
```
#### is.propertyDefined( object , path )
Checks whether `path` is a direct or inherited property of `object`.
```js
is.propertyDefined( Object.create( { foo : 'bar' } ) , 'foo' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.bar' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.bar.baz' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.qux.baz' ) // false
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.bar.baz.qux' ) // false
```
#### is.conforms( object , schema , [strict=false] )
Checks whether `object` conforms to `schema`.
A `schema` is an object whose properties are functions that takes
these parameters(in order):
- __value:any__ - The value of current iteration.
- __key:string__ - The corresponding key of current iteration.
- __context:object__ - The object in question.
These functions, or _validators_, are called for each corresponding key
in `object` to check whether object conforms to the schema. An object is
said to be conforms to the schema if all validators passed.
In strict mode(where `strict=true`), `is.conforms` also checks whether
`object` and `schema` has the same set of own, enumerable, string-keyed
properties, in addition to check whether all validators passed.
```js
is.conforms(
{ name : '/is' , access : 'public' } ,
{ name : is.exist }
) // true
is.conforms(
{ name : '/is' , access : 'public' } ,
{ description : is.string }
) // false; key `description` does not exist on `object`
is.conforms(
{ name : '/is' , access : 'public' } ,
{
name( value , key , context ) {
return is.exist( value ) && context.access === 'public'
}
}
) // true
//
// strict mode
//
is.conforms(
{
name : '/is' ,
access : 'public'
} ,
{
name( value , key , context ) {
return is.string( value ) && value.length >= 3
}
} ,
true // enable strict mode
) // false; `object` has extraneous properties
```
#### is.array( value )
Checks whether given value is an array.
```js
is.array( [] ) // true
is.array( '' ) // false
is.array( document.scripts ) // false
is.array( function() {} ) // false
```
#### is.arrayLikeObject( value )
Checks whether given value is an _array-like_ object.
An object is qualified as _array-like_ if it has a property named
`length` that is a positive safe integer. As a special case, functions
are never qualified as _array-like_.
```js
is.arrayLikeObject( [] ) // true
is.arrayLikeObject( '' ) // false
is.arrayLikeObject( document.scripts ) // true
is.arrayLikeObject( function() {} ) // false
```
#### is.inArray( value , array , [offset=0] , [comparator=is.equal] )
Checks whether given array or array-like object contains certain element.
- __value__: The element to search.
- __array__: The array or array-like object to search from.
- __offset__: The index to search from, inclusive.
- __comparator__: The comparator invoked per element against `value`.
```js
is.inArray( 2 , [ 1 , 2 , 3 ] ) // true
is.inArray( 4 , [ 1 , 2 , 3 ] ) // false
is.inArray( 2 , [ 1 , 2 , 3 ] , 1 ) // true
is.inArray( 2 , [ 1 , 2 , 3 ] , 2 ) // false
is.inArray( 2 , [ 1 , 2 , 3 ] , -2 ) // true; supports negative offset
is.inArray( 2 , [ 1 , 2 , 3 ] , 3 ) // false; offset out of range
is.inArray( 2 , [ 1 , 2 , 3 ] , -4 ) // false; offset out of range
is.inArray( [ 2 ] , [ 1 , [ 2 ] , 3 ] ) // false; default comparator is `is.equal`
is.inArray( [ 2 ] , [ 1 , [ 2 ] , 3 ] , 0 , is.deepEqual ) // true
is.inArray( [ 2 ] , [ 1 , [ 2 ] , 3 ] , is.deepEqual ) // true; `offset` can be omitted when passing a custom comparator only
is.inArray( 2 , [ 1 , 2 , 3 ] , ( val , arrMember ) => val === arrMember ) // true; `comparator` takes two parameters, the element to search and the array element of current iteration
```
#### is.sameType( value , other )
Checks whether given values are of the same type.
```js
is.sameType( 0 , 0 ) // true
is.sameType( 0 , '0' ) // false
is.sameType( 0 , new Number( 0 ) ) // false
is.sameType( 0 , Number.NaN ) // true
is.sameType( [] , {} ) // false
```
#### is.primitive( value )
Checks whether given value is a [primitive](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
```js
is.primitive( null ) // true
is.primitive( undefined ) // true
is.primitive( 0 ) // true
is.primitive( new Number( 0 ) ) // false
is.primitive( '' ) // true
is.primitive( new String( '' ) ) // false
is.primitive( true ) // true
is.primitive( new Boolean( true ) ) // false
is.primitive( Symbol() ) // true
is.primitive( Symbol.for( 'is' ) ) // true
is.primitive( {} ) // false
is.primitive( [] ) // false
is.primitive( function() {} ) // false
```
#### is.date( value )
Checks whether given value is a `Date` object.
```js
is.date( new Date() ) // true
```
#### is.error( value )
Checks whether given value is an `Error` object.
```js
is.error( new Error() ) // true
is.error( new TypeError() ) // true
```
#### is.function( value )
Checks whether given value is a function.
```js
is.function( function () {} ) // true
is.function( () => null ) // true
is.function( new Function() ) // true
```
#### is.map( value )
Checks whether given value is a `Map` object.
```js
is.map( new Map() ) // true
```
#### is.regexp( value )
Checks whether given value is a `RegExp` object.
```js
is.regexp( /^/ ) // true
is.regexp( new RegExp() ) // true
```
#### is.set( value )
Checks whether given value is a `Set` object.
```js
is.set( new Set() ) // true
```
#### is.symbol( value )
Checks whether given value is a symbol.
```js
is.symbol( Symbol() ) // true
is.symbol( Symbol.for( 'is' ) ) // true
```
#### is.equal( value , other )
Checks whether given values are equal, using [SameValueZero](http://bit.ly/1soiz3w) algorithm.
```js
is.equal( null , undefined ) // false
is.equal( 0 , 0 ) // true
is.equal( 0 , '0' ) // false
is.equal( +0 , -0 ) // true; SameValueZero
is.equal( Number.NaN , Number.NaN ) // true; SameValueZero
is.equal( [] , [] ) // false
```
#### is.deepEqual( value , other )
Checks whether given values are deeply equal, i.e:
- If `Type( value ) !== Type( other )`, returns `false`.
- For primitives, checks whether they are equal using _SameValueZero_.
- For arrays, checks whether they have same set of members, all of which are deeply equal.
- Otherwise, checks whether they have same set of own, enumerable, string keyed properties, all of which are deeply equal.
```js
is.deepEqual( null , undefined ) // false
is.deepEqual( 0 , 0 ) // true
is.deepEqual( 0 , '0' ) // false
is.deepEqual( +0 , -0 ) // true; SameValueZero
is.deepEqual( Number.NaN , Number.NaN ) // true; SameValueZero
is.deepEqual( [ 1 , { foo : [ 2 , [ 3 , 4 ] ] , bar : { baz : 5 } } ] , [ 1 , { foo : [ 2 , [ 3 , 4 ] ] , bar : { baz : 5 } } ] ) // true
is.deepEqual( Object.create( { foo : 1 } ) , Object.create( { foo : 2 } ) ) // true; only own, enumerable, string-keyed properties are checked
```
## Writing new predicates
_Predicates_ are essentially functions that checks whether certain condition met based on passed in arguments. They are packaged in various _bundles_. Conceptually, a bundle is simply a way
of organizing related predicates. Implementation-wise, a bundle is a just a
function that takes two parameters:
- `util:object` - The utility object.
- `is:object` - The `is` export.
The `util` object defines a method called `addPredicate` that allows you to define new predicates:
> util.addPredicate( name:string , predicate:function )
> - name - The name of the predicate.
> - predicate - The predicate function.
Once defined, the predicate will be available on both `is` and `is.not` — `util.addPredicate` wraps the predicate in a delegate function and automatically handles positive/negative cases for you.
Still confused? Take a look at this sample bundle:
```js
// my_bundle.js
// `util` and `is` are passed in as free variables, so you don't
// need to call `require( '@pwn/is' )`
module.exports = function bundle( util , is ) {
util.addPredicate( 'positive' , function isPositive( value ) {
return is.number( value ) && value > 0
} )
util.addPredicate( 'negative' , function isNegative( value ) {
return is.number( value ) && value < 0
} )
}
```
To use a bundle, simple call `is.use`:
> is.use( bundle:function )
```js
const is = require( '/is' )
// import all predicates from my_bundle.js
is.use( require( 'path/to/my_bundle' ) )
is.positive( +1 ) // true
is.not.positive( -1 ) // true
is.negative( -1 ) // true
is.not.negative( +1 ) // true
```