Minimalistic predicate library.
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
dist using npm scripts Jun 20, 2016
docs coding style Aug 12, 2016
lib coding style Aug 12, 2016
test tweaking saucelabs launchers Sep 2, 2016
.eslintrc using enums instead of numeric values in .eslintrc Jun 20, 2016
.gitignore updated .gitignore May 19, 2016
.npmignore using npm scripts Jun 20, 2016
.npmrc updated `.npmrc` May 23, 2016
.travis.yml reduce browser & env combinations to test Aug 12, 2016
README.md
package.json coding style Aug 12, 2016

README.md

is.js

version build status

saucelabs matrix

Minimalistic predicate library.

This is a general purpose check library, you may found tagOf useful if all you want is just check types.

Install

Node:

$ npm install --save @pwn/is

Browser:

<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:

let is = require( '@pwn/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

TL;DR

A bundle is simply a way of organizing related predicates.

bundle:nil

bundle:number

bundle:string

bundle:boolean

bundle:object

bundle:array

bundle:type

bundle:equality

API reference

is.null( value )

Checks whether given value is null.

is.null( null ) // true
is.null( undefined ) // false

is.undefined( value )

Checks whether given value is undefined.

is.undefined( null ) // false
is.undefined( undefined ) // true

is.exist( value )

Checks whether given value exists, i.e, not null nor undefined.

is.exist( null ) // false
is.exist( undefined ) // false

is.nil( value )

Checks whether given value is either null or undefined.

is.nil( null ) // true
is.nil( undefined ) // true

is.number( value )

Checks whether given value is a number.

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
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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

is.conforms(
    { name : '@pwn/is' , access : 'public' } ,
    { name : is.exist }
) // true

is.conforms(
    { name : '@pwn/is' , access : 'public' } ,
    { description : is.string }
) // false; key `description` does not exist on `object`

is.conforms(
    { name : '@pwn/is' , access : 'public' } ,
    {
        name( value , key , context ) {
            return is.exist( value ) && context.access === 'public'
        }
    }
) // true


//
// strict mode
//

is.conforms(
    {
        name : '@pwn/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.

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.

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.
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.

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.

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.

is.date( new Date() ) // true

is.error( value )

Checks whether given value is an Error object.

is.error( new Error() ) // true
is.error( new TypeError() ) // true

is.function( value )

Checks whether given value is a function.

is.function( function () {} ) // true
is.function( () => null ) // true
is.function( new Function() ) // true

is.map( value )

Checks whether given value is a Map object.

is.map( new Map() ) // true

is.regexp( value )

Checks whether given value is a RegExp object.

is.regexp( /^/ ) // true
is.regexp( new RegExp() ) // true

is.set( value )

Checks whether given value is a Set object.

is.set( new Set() ) // true

is.symbol( value )

Checks whether given value is a symbol.

is.symbol( Symbol() ) // true
is.symbol( Symbol.for( 'is' ) ) // true

is.equal( value , other )

Checks whether given values are equal, using SameValueZero algorithm.

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.
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.notutil.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:

// 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 )

let is = require( '@pwn/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