Minimalistic predicate library.
Node:
$ npm install --save @pwn/is
Browser:
<script src="path/to/is.min.js"></script>
- 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.
A code sample is worth a thousand words:
const 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 - List of available predicates shipped with
is.js
. - API reference - Detailed documentation on each predicate.
- Writing new predicates - Learn how to define new predicates.
TL;DR
A bundle is simply a way of organizing related predicates.
bundle:nil
bundle:number
- is.number( value )
- is.numeral( value )
- is.nan( value )
- is.odd( number )
- is.even( number )
- is.finite( number )
- is.infinite( number )
- is.integer( number )
- is.safeInteger( number )
bundle:string
- is.string( value )
- is.emptyString( string )
- is.substring( substring , string , [offset=0] )
- is.prefix( prefix , string )
- is.suffix( suffix , string )
bundle:boolean
bundle:object
- is.object( value )
- is.emptyObject( object )
- is.propertyDefined( object , path )
- is.conforms( object , schema , [strict=false] )
bundle:array
- is.array( value )
- is.arrayLikeObject( value )
- is.inArray( value , array , [offset=0] , [comparator=is.equal] )
bundle:type
- is.sameType( value , other )
- is.primitive( value )
- is.date( value )
- is.error( value )
- is.function( value )
- is.map( value )
- is.regexp( value )
- is.set( value )
- is.symbol( value )
bundle:equality
Checks whether given value is null
.
is.null( null ) // true
is.null( undefined ) // false
Checks whether given value is undefined
.
is.undefined( null ) // false
is.undefined( undefined ) // true
Checks whether given value exists, i.e, not null
nor undefined
.
is.exist( null ) // false
is.exist( undefined ) // false
Checks whether given value is either null
or undefined
.
is.nil( null ) // true
is.nil( undefined ) // true
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
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
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
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
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
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
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
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
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
Checks whether given value is a string.
is.string( 'lipsum' ) // true
is.string( new String( 'lipsum' ) ) // false
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
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
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
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
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
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
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
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
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
Checks whether given value is an array.
is.array( [] ) // true
is.array( '' ) // false
is.array( document.scripts ) // false
is.array( function() {} ) // false
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
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
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
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
Checks whether given value is a Date
object.
is.date( new Date() ) // true
Checks whether given value is an Error
object.
is.error( new Error() ) // true
is.error( new TypeError() ) // true
Checks whether given value is a function.
is.function( function () {} ) // true
is.function( () => null ) // true
is.function( new Function() ) // true
Checks whether given value is a Map
object.
is.map( new Map() ) // true
Checks whether given value is a RegExp
object.
is.regexp( /^/ ) // true
is.regexp( new RegExp() ) // true
Checks whether given value is a Set
object.
is.set( new Set() ) // true
Checks whether given value is a symbol.
is.symbol( Symbol() ) // true
is.symbol( Symbol.for( 'is' ) ) // true
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
Checks whether given values are deeply equal, i.e:
- If
Type( value ) !== Type( other )
, returnsfalse
. - 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
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
- Theis
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:
// 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 )
const 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