Set of various predicates for type checking, assertions, filtering etc
npm install predicatesSet of various predicates for type checking, simple assertions, filtering etc.
npm install predicates
`
Full API
Example
`js
const is = require('predicates');is.string(1); // false
is.string('test'); // true
is.undefinedOr(String, undefined); // true
is.undefinedOr(String, 'string'); // true
is.undefinedOr(is.string, undefined); // true
is.undefinedOr(is.string, 'timmy'); // true
is.undefinedOr(is.string)(undefined); // true
is.undefinedOr(is.string)('timmy'); // true
const isPerson = is.structure({
name: is.string,
surname: is.undefinedOr(is.string),
age: is.number
});
isPerson({name: 'Tom', age: 10}); // true
isPerson({surname: 'Welling', age: 100}); // false, lack of name property
` `js
const assertName = is.assert(is.string);
const assertSurname = is.assert(is.notBlank);
const assertAge = is.assert(is.undefinedOr(is.positive));const Person = function(name, surname, age) {
assertName(name);
assertSurname(surname);
assertAge(age);
}
new Person('Tom', 'Welling', 33); // OK!
new Person('Tom', 'Welling'); // OK!
new Person('Tom', '', 33); // Error: Surname must be a string and cannot be emptye
`API design
$3
Most of type checking, utility libraries force you use predicates with only one argument but _predicates_ doesn.t
Additionally _predicates_ preserves the context of function call which allows you to create even more powerful logic.
`js
const is = require('predicates');const isOkToModifyTags = is.all(
is.arrayOf(is.string),
function(tags, previousTags) {
// no need to save them again if they are the same as previous ones
return tags.join(',') !== previousTags.join(',');
}
);
Module.prototype.modifyTags = function(entityId, tags) {
var previousTags = getTags(entityId);
if (isOkToModifyTags(tags, previousTags)) {
this.saveTags(entityId, tags);
} else {
// no need to save them again if they are the same as previous ones
}
}
`$3
_Predicates_ checks whether generated predicate is misconfigured and throws an error as fast as possible.`js
is.startsWith(''); // Error: Prefix cannot be empty
// since that would be true for all stringsis.in([]); // Error: Collection cannot be empty
// always false
`That's why it's a good practice to create predicates at the beginning of a module definition to quickly catch any mistake.
`js
// some module
const is = require('predicates');
const isImage = is.in([]); // Error: Collection cannot be empty// You don't need to run the whole application to get the error that your predicate is wrong
export class Module {
}
`$3
You don't need to check the arguments provided to predicates to make sure they won't cause an error - _predicates_ does it for you.`js
const isDuck = is.hasProperty('quack');isDuck(undefined); // false - no error
isDuck(1); // false - no error
isDuck('duck'); // false - no error
is.matches(/.*\.ts/)(100); // false - no error
`NOTE! This rule applies only for predicates defined in the library. Any user-defined predicate MAY throw errors (however I don't advise to do so) and _predicates_ will not catch them.
`
const assertName = is.all(is.string, function(value) {
if (value === 'admin') {
throw new Error('Admin is a reserved user name');
}
});assertName('admin'); // Error: Admin is a reserved user name
`$3
Every predicate (if possible) is a type guard
`typescript
if (is.string(value)) {
// at this point typescript compiler knows that value is a string
}
`$3
`js
is.property('foo', is.string)({foo: 'bar'}); // true// for less verbosity this is possible as well
is.property('foo', String)({foo: 'bar'}); // true
is.arrayOf(String)(['foo']); // true
``