{"id":22202188,"url":"https://github.com/rumkin/typed-props","last_synced_at":"2025-07-27T04:31:30.912Z","repository":{"id":48020287,"uuid":"98366278","full_name":"rumkin/typed-props","owner":"rumkin","description":"Facebook's PropTypes standalone extensible implementation for browser and server","archived":false,"fork":false,"pushed_at":"2023-01-03T15:14:10.000Z","size":464,"stargazers_count":9,"open_issues_count":7,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-01T13:30:57.875Z","etag":null,"topics":["checker","js","typecheck","typescript","validation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rumkin.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":"2017-07-26T01:42:55.000Z","updated_at":"2019-09-12T10:37:52.000Z","dependencies_parsed_at":"2023-02-01T06:45:39.852Z","dependency_job_id":null,"html_url":"https://github.com/rumkin/typed-props","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rumkin/typed-props","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Ftyped-props","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Ftyped-props/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Ftyped-props/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Ftyped-props/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rumkin","download_url":"https://codeload.github.com/rumkin/typed-props/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumkin%2Ftyped-props/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265137585,"owners_count":23716882,"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":["checker","js","typecheck","typescript","validation"],"created_at":"2024-12-02T16:12:41.142Z","updated_at":"2025-07-27T04:31:30.654Z","avatar_url":"https://github.com/rumkin.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![TypedProps](doc/cover.png)\n\n---\n\n[![npm](https://img.shields.io/npm/v/typed-props.svg?style=flat-square)](https://npmjs.com/package/typed-props)\n[![Travis](https://img.shields.io/travis/rumkin/typed-props.svg?style=flat-square)](https://travis-ci.org/rumkin/typed-props)\n![](https://img.shields.io/badge/coverage-100%25-green.svg?style=flat-square)\n![](https://img.shields.io/badge/size-13.0%20KiB-blue.svg?style=flat-square)\n![](https://img.shields.io/badge/deps-0-blue.svg?style=flat-square)\n[![npm](https://img.shields.io/npm/dm/typed-props.svg?style=flat-square)](https://npmjs.com/package/typed-props)\n\nFacebook's PropTypes-alike interface implementation for client and server, reusable\nand extensible. It produce error reports instead of throwing or printing into\nconsole. It works *without React*.\n\n[Gitter](https://gitter.im/TypedProps)\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Examples](#examples)\n- [Standard checks](#standard-checks)\n- [Non-standard checks](#non-standard-checks)\n- [Decorators](#decorators)\n- [Checks and groups](#checks-and-groups)\n- [Extension](#extension)\n- [API](#api)\n- [License](#license)\n\n## Installation\n\nVia npm:\n```shell\nnpm i typed-props\n```\n\nOr via unpkg.com:\n\n```html\n\u003cscript src=\"https://unpkg.com/typed-props@1/dist/typed-props.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/typed-props@1/dist/typed-props.min.js\"\u003e\u003c/script\u003e\n```\n\nComplete [usage guide](https://github.com/rumkin/typed-props/tree/master/doc).\n\n## Usage\n\nCustom types check:\n\n```javascript\n\nimport {Type as T, StrictType as ST, check} from 'typed-props'\n\nconst type = T.shape({\n  id: T.number.isRequired,\n  name: T.string.isRequired,\n  email: T.string,\n}).isRequired\n\n// Or\n\nconst type = ST.shape({\n  id: ST.number,\n  name: ST.string,\n  email: ST.string.optional,\n})\n\nconst data = {\n  id: '1',\n  name: null\n}\n\nconst issues = check(data, type)\n```\n\n### Output\n\nResult of validation is an Array of Issues. Issue is an object which describes\nvalidator rules violation.\n\nIssue typing:\n```typescript\nexport type Issue = {\n  rule: string\n  path: Array\u003cstring|number\u003e\n  details: {\n    reason: string\n    [key:string]: any\n  }\n}\n```\n\nExample:\n\n```javascript\n[\n  {\n    // Violated rule.\n    rule: 'type',\n    // Value location. It helps to receive value from nested object.\n    path: ['user', 'messages', 0],\n    // Details explain what exactly goes wrong.\n    details: {\n      // Reason helps to identify kind of problem within one validator.\n      // Usual values are mismatch, no_matches, and redundant.\n      reason: 'mismatch',\n      // The next values are validator dependent.\n      type: 'string',\n      expect: true,\n      is: false,\n    }\n  }\n]\n```\n\n## Examples\n\n* Create [UniqItems check](examples/uniq-items.js).\n* [Describe API](examples/api.js) with TypedProps (with circular types resolution).\n\n## Standard checks\n\nStandard checks provided by Facebook's PropTypes:\n\n```javascript\nimport {Type, TypeStore} from 'typed-props'\n\n// Object properties should pass all checks.\nconst shape = Type.shape({\n  // Any value except of undefined\n  anything: Type.isRequired,\n  // Which is equivalent of\n  anythingElse: Type.any.isRequired,\n  // Number property\n  number: Type.number,\n  // String property\n  string: Type.string,\n  // Boolean property\n  bool: Type.bool,\n  // Object property\n  object: Type.object,\n  // Array property\n  array: Type.array,\n  // Array property\n  func: Type.func,\n  // Symbol property\n  symbol: Type.symbol,\n  // Property which value is instance of Date\n  instanceOf: Type.instanceOf(Date),\n\n  // Complex rules\n\n  // One of check if value is in list of passed primitives\n  // It works like an enum\n  oneOf: ['one', 'two'],\n  // Check if all array values match the passed TypedProps\n  arrayOf: Type.number,\n  // Check if value is matched any of passed TypedProps.\n  oneOfType: Type.oneOfType([\n    Type.number,\n    Type.string,\n  ]),\n  // Check if all object properties passes the TypedProps.\n  objectOf: Type.objectOf(Type.number),\n  // Check shape has described properties and no other props.\n  exactShape: Type.exact({\n    id: Type.number,\n    name: Type.string,\n  }),\n  // Exact shape with custom props\n  exactShape: Type.exactFuzzy({\n    id: Type.number,\n    name: Type.string,\n  }, [/Id$/, Type.string]),\n})\n\nconst issues = check({}, shape) // =\u003e [{path:['anything'], rule: 'isRequired', details: {is: false}}]\n```\n\nResult of `check` call is array of [issues](#issue-type). If there is no issues, this array will be\nempty.\n\n\u003e ⚠️ If shape/exact rule property presented by function it should return type to check.\n\n\u003e ⚠️ .object will fail for arrays and vice versa.\n\n## Named and circular types\n\nUsing named types it's possible to created nested structures with cross references.\nIt could be useful for validating complex data types. Also names help to produce more\nmeaningful error reports.\n\n```javascript\nconst store = new TypeStore()\n\nconst userType = Type.shape({\n  id: Type.number.isRequired,\n  name: Type.string.isRequired,\n  friends: Type.arrayOf(\n    store.ref('User')\n  ),\n})\n\nstore.add('User', userType)\n```\n\n## Non-standard checks\n\n```javascript\nType.shape({\n  // Make type optional\n  optionalValue: Type.optional,\n  // Determine type in runtime\n  propertyDependentType: Type.select(\n    [\n      ({type}) =\u003e type === 'ADD_TODO',\n      Type.shape({/* ADD_TODO action payload shape */}),\n    ],\n    [\n      ({type}) =\u003e type === 'SET_COMPLETED',\n      Type.shape({/* SET_COMPLETED action payload shape */}),\n    ],\n    [\n      () =\u003e true,\n      Type.any\n    ],\n  ),\n  // Create custom checks when TypedProps is not enough.\n  customValue: Type.custom((value) =\u003e value === Math.PI),\n})\n```\n\nTypedProps have it's own custom checks which make it more handful.\n\n### `Checkable.optional`\n\nThis is pseudo check. This rule allows to make some property optional. It can\nswitch off previously defined `.isRequired` check. It's better to use with `StrictType`.\n\n```javascript\nStrictType.number.optional\n```\n\n### `Checkable.is()`\n```\n(value:*) -\u003e Checkable\n```\n\nThis check validates the checkable value to strict equal `value` argument.\n\n```javascript\nType.is('user')\n```\n\n### `Checkable.select()`\n```\n(...Function|Checkable) -\u003e Checkable\n```\n\nThis checker allow to dynamically switch between types depending on input value.\nIt selects the first arguments that is not a function or if it's function and\nit returns something truly. Then use it as type to check.\n\n```javascript\nType.select(\n  [(value) =\u003e (typeof value === 'string'), Type.string],\n  [(value) =\u003e (typeof value === 'number'), Type.number],\n  [() =\u003e true, Type.any] // Otherwise accept anything\n)\n```\n\n### `Checkable.exactFuzzy()`\n```\n(shape:ShapeType, fuzzy:...[RegExp, Checkable]) -\u003e Checkable\n\nShapeType = Object\u003ckey,Checkable|Shape\u003e\n```\n\nCheck exact shape with fuzzy properties which keys should match regexp from fuzzy params.\n\n```javascript\nconst fuzzy = Type.exactFuzzy({}, [/Id$/, Type.number])\ncheck({userId: 1, postId: 2}, fuzzy)\n```\n\n### `Checkable.custom()`\n```\n(check:(it:*) -\u003e bool) -\u003e Checkable\n```\n\nCustom check accepts `check` argument and use it to validate the value.\n\n## Decorators\n\n__Experimental Feature__. Decorators can check function arguments and value it returns in runtime.\n\n\u003e ⚠️ Decorators throw CheckError with `issues` property.\n\n```javascript\nimport {StrictType as T, args, result} from 'typed-props'\n\nclass Arith {\n  // Fixed arguments length example\n  @args(T.number, T.number)\n  @result(T.number)\n  add(a, b) {\n    return a + b\n  }\n\n  // Variadic argument's length example\n  @args(T.number, [T.number])\n  @result(T.number)\n  addAll(a = 0, ...numbers) {\n    return numbers.reduce((sum, b) =\u003e sum + b, a)\n  }\n}\n```\n\n## Checks and groups\n\nCurrently there are several groups of checkers: existence, type, exact, and complex checks.\n\n* Existance:\n  * isRequired\n  * optional: removes isRequired\n* Type:\n  * bool\n  * number\n  * string\n  * func\n  * object\n  * array\n  * any: removes any other type check\n* Exact:\n  * is\n  * oneOf\n* Complex:\n  * oneOfType\n  * arrayOf: overwirites type check with `array`\n  * objectOf: overwirites type check with `object`\n  * shape: replaces exact\n  * exact: replaces shape\n  * select\n  * custom\n\nType and existence checks are switchable and can replace each other. It's made\nfor flexibility.\n\n```javascript\nType.isRequired.number.string.func // -\u003e final check is \"required function\".\n```\n\nIn the same time the complex checks like `shape` or `arrayOf` require the input value to has certain\ntype object and array respectively. They will overwrite type checks too. But overwiting of complex types\ncurrently isn't possible because of unexpected behaviour. It could leads to runtime errors.\nSo it strongly recommended not to overwrite such checks.\n\nIt could be changed in the future.\n\n```javascript\nType.arrayOf(Type.number).isRequired.number // Will throw an error in runtime\n```\n\n## Extension\n\nTypedProps support extension throught inheritance. So you can create new type using\n`extend` on Type class or mixing in new rules with `Object.defineProperty`.\nMore real life example is in repository [examples](./examples) directory.\n\n```javascript\nclass IsFinite extends SimpleRule {\n  static ruleName = 'isFinite'\n\n  static checkIt(it) {\n    return isFinite(it)\n  }\n}\n\nclass MyTypes extends Type {\n  static get isFinite() {\n    return new this([\n      IsFinite.create([], isFinite.config(true))\n    ])\n  }\n\n  get isFinite() {\n    return new this.constructor(\n      isFinite.create(\n        this.getChecks(),\n        isFinite.config(true),\n      )\n    )\n  }\n}\n// Mixin into TypedProps\nObject.defineProperty(Type, 'isFinite', {\n    get() {\n        return new this(\n            IsFinite.create([], IsFinite.config())\n        )\n    },\n})\n\nObject.define(Type.prototype, 'isFinite', {\n  get() {\n    const checks = IsFinite.create(\n      this.getChecks(), IsFinite.config()\n    )\n    return new this.constructor(checks)\n  },\n})\n```\n\n### Rule types\n\nThere is several Rules which are using internally.\n\n#### UniqRule\n\nThis is probably the most useful type. This rule overwrites any other\noccurencies of the rule in type's rules array. It defines it's own\n`create` method which shouldn't be overriden by custom implementation. Mostly\nbecause it senseless.\n\n#### SimpleRule\n\nThis rule extends `UniqRule` and define it's own `check` method which take all\nwork by creating non-check logic (issue createsion, result comparision). It\nrequires `ckeckIt` method wich should return `boolean` value.\n\n```javascript\nclass IsArray extends SimpleRule {\n    static ruleName = 'isArray'\n\n    static checkIt(it) {\n        return Array.isArray(it)\n    }\n}\n```\n\n## API\n\n### `Checkable()`\n\nCheckable is a prototype of TypeProps. It contains only check logic and has no own rules.\n\n### `Checkable#getChecks()`\n```\n() -\u003e Checks[]\n```\n\nReturns a list of all defined checks from the TypedProps instance.\n\n### `check()`\n```text\n(value:*, type:Checkable) -\u003e Array.\u003cIssue\u003e\n```\n\nValidate `value` to satisfy `type` requirements. Always produce an Array of Issues.\n\n### `getRuleParams()`\n\n```text\n(type:TypedProps, name:string) -\u003e null|*[]\n```\n\n* `type` - Target type.\n* `name` - Rule name.\n* `=` Returns check params object or null if rule isn't found.\n\n\nReceive `rule` params by its' name.\n\n### `listRules()`\n\n```\n(type:TypedProps) -\u003e string[]\n```\n\n* `type` - Target type.\n* `=` Returns list of rule name in order they were defined.\n\n### `Rule{}`\n```\n{\n    ruleName: string\n    config: (...args[]) -\u003e RuleParams\n    create: (options:Array.\u003cCheck\u003e, params:RuleParams) -\u003e Array.\u003cCheck\u003e\n    check: (it:*, params:RuleParams, self:Checkable) -\u003e Array.\u003cIssue\u003e\n}\n```\n\nRule is an object which contains several methods required for TypeProps to work:\n\n#### `Rule.config()`\n```\n(...args:*) -\u003e Object\n```\n\nReceives arguments from call and transform them to Rule internal representation.\nThis representation could be different from rule to rule.\n\n#### `Rule.create()`\n```\n(checks:Check[], params:object) -\u003e Checks[]\n```\n\nAdds new check into array of already existing checks. It can overwrite\nany rule defined earlier when it is necessary. Also it can modify a rule\ndefined previously. But in most cases it just remove previously defined rule\nand push new one to the end.\n\n#### `Rule.check()`\n```\nCheckFunction\n```\n\nReceives `value` and checks that value is satisfying rule logic with `params`. If it's\nnot, then method returns list of found issues.\n\n### `Issue{}`\n```text\n{\n  path: Array.\u003cString|Number\u003e\n  rule: String\n  details: Object\n}\n```\n\n### `Check{}`\n```\n{\n  rule: String,\n  params: Object\n  check: CheckFunction\n}\n```\n\n### `CheckFunction()`\n```\n(value:*, params:Object) -\u003e Issue[]\n```\n\nObject representing validation failure.\n\n### License\n\nCopyright \u0026copy; 2018–2019, Rumkin. Released under [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frumkin%2Ftyped-props","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frumkin%2Ftyped-props","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frumkin%2Ftyped-props/lists"}