{"id":13750014,"url":"https://github.com/wookieb/predicates","last_synced_at":"2025-04-06T13:11:32.950Z","repository":{"id":22751479,"uuid":"26096909","full_name":"wookieb/predicates","owner":"wookieb","description":"Predicates for type checking, assertions, filtering etc","archived":false,"fork":false,"pushed_at":"2019-05-06T21:03:00.000Z","size":366,"stargazers_count":89,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-30T12:07:33.502Z","etag":null,"topics":["filtering","predicates","type-checking","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wookieb.png","metadata":{"files":{"readme":"README.MD","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-02T23:47:49.000Z","updated_at":"2023-07-03T15:49:21.000Z","dependencies_parsed_at":"2022-07-27T03:32:07.075Z","dependency_job_id":null,"html_url":"https://github.com/wookieb/predicates","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wookieb%2Fpredicates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wookieb%2Fpredicates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wookieb%2Fpredicates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wookieb%2Fpredicates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wookieb","download_url":"https://codeload.github.com/wookieb/predicates/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247485288,"owners_count":20946398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filtering","predicates","type-checking","typescript"],"created_at":"2024-08-03T07:01:22.159Z","updated_at":"2025-04-06T13:11:32.925Z","avatar_url":"https://github.com/wookieb.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Predicates\n[![Build Status](https://travis-ci.org/wookieb/predicates.svg)](https://travis-ci.org/wookieb/predicates)\n[![NPM version](https://badge.fury.io/js/predicates.svg)](http://badge.fury.io/js/predicates)\n[![Coverage Status](https://coveralls.io/repos/github/wookieb/predicates/badge.svg?branch=master)](https://coveralls.io/github/wookieb/predicates?branch=master)\n\nSet of various predicates for type checking, simple assertions, filtering etc.\n\n## Features\n* written in typescript (with [type guards](#type-guards) and function overloading)\n* well defined [API design principles](#api-design)\n* predicates description every predicate contains a proper description for easier debugging and automatic assertion generation\n* supports simple type checks with unnecessary verbosity\n* every predicate supports currying if possible\n\n## Install\n```\nnpm install predicates\n```\n## [Full API](API.md)\n\n## Example\n\n```js\nconst is = require('predicates');\n\nis.string(1); // false\nis.string('test'); // true\n\nis.undefinedOr(String, undefined); // true\nis.undefinedOr(String, 'string'); // true\nis.undefinedOr(is.string, undefined); // true\nis.undefinedOr(is.string, 'timmy'); // true\nis.undefinedOr(is.string)(undefined); // true\nis.undefinedOr(is.string)('timmy'); // true\n\nconst isPerson = is.structure({\n\tname: is.string,\n\tsurname: is.undefinedOr(is.string),\n\tage: is.number\n});\n\nisPerson({name: 'Tom', age: 10}); // true\nisPerson({surname: 'Welling', age: 100}); // false, lack of name property\n``` \n\n```js\nconst assertName = is.assert(is.string);\nconst assertSurname = is.assert(is.notBlank);\nconst assertAge = is.assert(is.undefinedOr(is.positive));\n\nconst Person = function(name, surname, age) {\n    assertName(name);\n    assertSurname(surname);\n    assertAge(age);\n}\n\nnew Person('Tom', 'Welling', 33); // OK!\nnew Person('Tom', 'Welling'); // OK!\nnew Person('Tom', '', 33); // Error: Surname must be a string and cannot be emptye\n```\n\n## API design\n\n### Generated predicates can be called with more than one argument\n\nMost of type checking, utility libraries force you to use predicates with only one argument but _predicates_ doesn't.\nAdditionally, _predicates_ preserves the context of function calls which allows you to create even more powerful logic.\n\n\n```js\nconst is = require('predicates');\n\nconst isOkToModifyTags = is.all(\n    is.arrayOf(is.string), \n    function(tags, previousTags) {\n        // no need to save them again if they are the same as previous ones\n        return tags.join(',') !== previousTags.join(',');\n    }\n);\n\nModule.prototype.modifyTags = function(entityId, tags) {\n    var previousTags = getTags(entityId);\n    if (isOkToModifyTags(tags, previousTags)) {\n        this.saveTags(entityId, tags);\n    } else {\n        // no need to save them again if they are the same as previous ones\n    }\n}\n```\n\n### Prevents stupid mistakes (fail fast)\n_Predicates_ checks whether generated a predicate is misconfigured and throws an error as fast as possible.\n\n```js\nis.startsWith(''); // Error: Prefix cannot be empty\n// since that would be true for all strings\n\nis.in([]); // Error: Collection cannot be empty\n// always false\n```\n\nThat's why it's a good practice to create predicates at the beginning of a module definition to quickly catch any mistakes.\n\n```js\n// some module\nconst is = require('predicates');\nconst isImage = is.in([]); // Error: Collection cannot be empty\n\n// You don't need to run the whole application to get the error that your predicate is wrong\nexport class Module {\n    \n}\n```\n\n### Defined and generated predicates will never throw any error\nYou don't need to check the arguments provided to predicates to make sure they won't cause an error - _predicates_ does it for you.\n\n```js\nconst isDuck = is.hasProperty('quack');\n\nisDuck(undefined); // false - no error\nisDuck(1); // false - no error\nisDuck('duck'); // false - no error\n\nis.matches(/.*\\.ts/)(100); // false - no error\n```\n\nNOTE! 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.\n\n```\nconst assertName = is.all(is.string, function(value) {\n    if (value === 'admin') {\n        throw new Error('Admin is a reserved user name');\n    }\n});\n\nassertName('admin'); // Error: Admin is a reserved user name\n```\n\n### Type guards \nEvery predicate (if possible) is a type guard\n```typescript\nif (is.string(value)) {\n   // at this point typescript compiler knows that value is a string \n}\n```\n\n### Core types are automatically translated to proper predicate\n\n```js\nis.property('foo', is.string)({foo: 'bar'}); // true\n\n// for less verbosity this is possible as well\nis.property('foo', String)({foo: 'bar'}); // true\nis.arrayOf(String)(['foo']); // true\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwookieb%2Fpredicates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwookieb%2Fpredicates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwookieb%2Fpredicates/lists"}