{"id":13400691,"url":"https://github.com/gcanti/tcomb-react","last_synced_at":"2025-03-14T06:31:52.200Z","repository":{"id":20181958,"uuid":"23452965","full_name":"gcanti/tcomb-react","owner":"gcanti","description":"Alternative syntax for PropTypes","archived":true,"fork":false,"pushed_at":"2018-07-15T06:42:00.000Z","size":461,"stargazers_count":202,"open_issues_count":3,"forks_count":13,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-06T15:48:58.565Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/gcanti.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-08-29T04:50:20.000Z","updated_at":"2023-03-08T03:13:46.000Z","dependencies_parsed_at":"2022-07-21T07:33:21.069Z","dependency_job_id":null,"html_url":"https://github.com/gcanti/tcomb-react","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gcanti%2Ftcomb-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gcanti%2Ftcomb-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gcanti%2Ftcomb-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gcanti%2Ftcomb-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gcanti","download_url":"https://codeload.github.com/gcanti/tcomb-react/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243313394,"owners_count":20271173,"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":[],"created_at":"2024-07-30T19:00:54.665Z","updated_at":"2025-03-14T06:31:52.193Z","avatar_url":"https://github.com/gcanti.png","language":"JavaScript","readme":"[![build status](https://img.shields.io/travis/gcanti/tcomb-react/master.svg?style=flat-square)](https://travis-ci.org/gcanti/tcomb-react)\n[![dependency status](https://img.shields.io/david/gcanti/tcomb-react.svg?style=flat-square)](https://david-dm.org/gcanti/tcomb-react)\n![npm downloads](https://img.shields.io/npm/dm/tcomb-react.svg)\n\n# Features\n\n- **by default props are required**, a saner default since it's quite easy to forget `.isRequired`\n- **checks for unwanted additional props**\n- **documentation** (types and comments) can be automatically extracted\n- additional fine grained type checks, nestable at arbitrary level\n- builds on [tcomb](https://github.com/gcanti/tcomb), [tcomb-validation](https://github.com/gcanti/tcomb-validation), [tcomb-doc](https://github.com/gcanti/tcomb-doc) libraries\n\n# Compatibility\n`tcomb-react` has been tested and found working on the following targets.\nThe list is not exhaustive and `tcomb-react` will probably work on other versions that haven't been listed.\n\nReact: `^0.13.0`, `^0.14.0`, `^15.0.0`\n\n# Prop types\n\n## The `@props` decorator (ES7)\n\nFor an equivalent implementation in ES5, or for Stateless Components, see the `propTypes` function below.\n\n**Signature**\n\n```js\ntype Props = {[key: string]: TcombType};\n\ntype PropsType = TcombStruct | TcombInterface;\n\ntype Type = Props | PropsType | Refinement\u003cPropsType\u003e;\n\ntype Options = {\n  strict?: boolean // default true\n};\n\n@props(type: Type, options?: Options)\n```\n\nwhere\n\n- `type` can be a map `string -\u003e TcombType`, a `tcomb` struct, a `tcomb` interface, a refinement of a `tcomb` struct / interface, a refinement of a `tcomb` interface\n- `options`:\n  - `strict: boolean` (default `true`) if `true` checks for unwanted additional props\n\n**Example** (ES7)\n\n```js\nimport t from 'tcomb'\nimport { props } from 'tcomb-react'\n\nconst Gender = t.enums.of(['Male', 'Female'], 'Gender')\nconst URL = t.refinement(t.String, (s) =\u003e s.startsWith('http'), 'URL')\n\n@props({\n  name: t.String,             // a required string\n  surname: t.maybe(t.String), // an optional string\n  age: t.Number,              // a required number\n  gender: Gender,             // an enum\n  avatar: URL                 // a refinement\n})\nclass Card extends React.Component {\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003e{this.props.name}\u003c/p\u003e\n        ...\n      \u003c/div\u003e\n    )\n  }\n\n}\n```\n\n**Unwanted additional props**\n\nBy default `tcomb-react` checks for unwanted additional props:\n\n```js\n@props({\n  name: t.String\n})\nclass Person extends React.Component {\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003e{this.props.name}\u003c/p\u003e\n      \u003c/div\u003e\n    )\n  }\n\n}\n\n...\n\n\u003cPerson name=\"Giulio\" surname=\"Canti\" /\u003e\n```\n\n**Output**\n\n```\nWarning: Failed propType: [tcomb] Invalid additional prop(s):\n\n[\n  \"surname\"\n]\n\nsupplied to Person.\n```\n\n**Note**. You can **opt-out** passing the `option` argument `{ strict: false }`.\n\n## The `propTypes` function\n\n**Signature**\n\nSame as `@props`.\n\n**Stateless Component Example**\n\n```js\nimport { propTypes } from 'tcomb-react'\n\nconst MyComponentProps = t.interface({\n  name: t.String,\n});\n\nconst MyComponent = (props) =\u003e (\n  \u003cdiv /\u003e\n);\nMyComponent.propTypes = propTypes(MyComponentProps);\n```\n\n**ES5 `React.createClass` Example**\n\n```js\nvar t = require('tcomb');\nvar propTypes = require('tcomb-react').propTypes;\n\nvar Gender = t.enums.of(['Male', 'Female'], 'Gender');\nvar URL = t.refinement(t.String, function (s) { return s.startsWith('http'); }, 'URL');\n\nvar Card = React.createClass({\n\n  propTypes: propTypes({\n    name: t.String,             // a required string\n    surname: t.maybe(t.String), // an optional string\n    age: t.Number,              // a required number\n    gender: Gender,             // an enum\n    avatar: URL                 // a refinement\n  }),\n\n  render: function () {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003e{this.props.name}\u003c/p\u003e\n        ...\n      \u003c/div\u003e\n    );\n  }\n\n});\n```\n\n## How it works\n\nThe `@props` decorator sets `propTypes` on the target component to use a [custom validator function](https://facebook.github.io/react/docs/reusable-components.html#prop-validation) built around tcomb types for each specified prop.\n\nFor example, the following:\n\n```js\nconst URL = t.refinement(t.String, (s) =\u003e s.startsWith('http'), 'URL');\n\n@props({\n  name: t.String,\n  url: URL,\n})\nclass MyComponent extends React.Component {\n  // ...\n}\n```\n\nis roughly equivalent to:\n\n```js\nconst URL = t.refinement(t.String, (s) =\u003e s.startsWith('http'), 'URL');\n\nclass MyComponent extends React.Component {\n  // ...\n}\nMyComponent.propTypes = {\n  name: function(props, propName, componentName) {\n    if (!t.validate(props[propName], t.String).isValid()) {\n      return new Error('...');\n    }\n  },\n  url: function(props, propName, componentName) {\n    if (!t.validate(props[propName], URL).isValid()) {\n      return new Error('...');\n    }\n  },\n}\n```\n\n## The babel plugin\n\nUsing [babel-plugin-tcomb](https://github.com/gcanti/babel-plugin-tcomb) you can express `propTypes` as Flow type annotations:\n\n```js\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport type { $Refinement } from 'tcomb'\nimport { props } from 'tcomb-react'\n\ntype Gender = 'Male' | 'Female';\n\nconst isUrl = (s) =\u003e s.startsWith('http')\ntype URL = string \u0026 $Refinement\u003ctypeof isUrl\u003e;\n\ntype Props = {\n  name: string,\n  surname: ?string,\n  age: number,\n  gender: Gender,\n  avatar: URL\n};\n\n@props(Props)\nclass Card extends React.Component {\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003e{this.props.name}\u003c/p\u003e\n        ...\n      \u003c/div\u003e\n    )\n  }\n\n}\n```\n\n# Extract documentation from your components\n\n## The `parse` function\n\nGiven a path to a component file returns a JSON / JavaScript blob containing **props types, default values and comments**.\n\n**Signature**\n\n```js\n(path: string | Array\u003cstring\u003e) =\u003e Object\n```\n\n**Example**\n\nSource\n\n```js\nimport t from 'tcomb'\nimport { props } from 'tcomb-react'\n\n/**\n * Component description here\n * @param name - name description here\n * @param surname - surname description here\n */\n\n@props({\n  name: t.String,             // a required string\n  surname: t.maybe(t.String)  // an optional string\n})\nexport default class Card extends React.Component {\n\n  static defaultProps = {\n    surname: 'Canti'          // default value for surname prop\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003e{this.props.name}\u003c/p\u003e\n        \u003cp\u003e{this.props.surname}\u003c/p\u003e\n      \u003c/div\u003e\n    )\n  }\n}\n```\n\nUsage\n\n```js\nimport parse from 'tcomb-react/lib/parse'\nconst json = parse('./components/Card.js')\nconsole.log(JSON.stringify(json, null, 2))\n```\n\nOutput\n\n```json\n{\n  \"name\": \"Card\",\n  \"description\": \"Component description here\",\n  \"props\": {\n    \"name\": {\n      \"kind\": \"irreducible\",\n      \"name\": \"String\",\n      \"required\": true,\n      \"description\": \"name description here\"\n    },\n    \"surname\": {\n      \"kind\": \"irreducible\",\n      \"name\": \"String\",\n      \"required\": false,\n      \"defaultValue\": \"Canti\",\n      \"description\": \"surname description here\"\n    }\n  }\n}\n```\n\n**Note**. Since `parse` uses runtime type introspection, your components should be `require`able from your script (you may be required to shim the browser environment).\n\n**Parsing multiple components**\n\n```js\nimport parse from 'tcomb-react/lib/parse'\nimport path from 'path'\nimport glob from 'glob'\n\nfunction getPath(file) {\n  return path.resolve(process.cwd(), file);\n}\n\nparse(glob.sync('./components/*.js').map(getPath));\n```\n\n## The `toMarkdown` function\n\nGiven a JSON / JavaScript blob returned by `parse` returns a markdown containing the components documentation.\n\n**Signature**\n\n```js\n(json: Object) =\u003e string\n```\n\n**Example**\n\nUsage\n\n```js\nimport parse from 'tcomb-react/lib/parse'\nimport toMarkdown from 'tcomb-react/lib/toMarkdown'\nconst json = parse('./components/Card.js')\nconsole.log(toMarkdown(json));\n```\n\nOutput\n\n```markdown\n## Card\n\nComponent description here\n\n**Props**\n\n- `name: String` name description here\n- `surname: String` (optional, default: `\"Canti\"`) surname description here\n\n```\n\n# Augmented pre-defined types\n\n`tcomb-react` exports some useful pre-defined types:\n\n- `ReactElement`\n- `ReactNode`\n- `ReactChild`\n- `ReactChildren`\n\n**Example**\n\n```js\nimport { props, ReactChild } from 'tcomb-react';\n\n@props({\n  children: ReactChild // only one child is allowed\n})\nclass MyComponent extends React.Component {\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        {this.props.children}\n      \u003c/div\u003e\n    );\n  }\n\n}\n```\n\n# Support for babel-plugin-tcomb\n\nThe following types for Flow are exported:\n\n- `ReactElementT`\n- `ReactNodeT`\n- `ReactChildT`\n- `ReactChildrenT`\n\n# Comparison table\n\n| Type | React | tcomb-react |\n|------|-------|-------------|\n| array | array | Array |\n| boolean | bool | Boolean |\n| functions | func | Function |\n| numbers | number | Number |\n| objects | object | Object |\n| strings | string | String |\n| all | any | Any |\n| required prop | T.isRequired | T |\n| optional prop | T | maybe(T) |\n| custom types | ✘ | ✓ |\n| tuples | ✘ | tuple([T, U, ...]) |\n| lists | arrayOf(T) | list(T) |\n| instance | instanceOf(A) | T |\n| dictionaries | objectOf(T) | dict(T, U) (keys are checked) |\n| enums | oneOf(['a', 'b']) | enums.of('a b') |\n| unions | oneOfType([T, U]) | union([T, U]) |\n| duck typing | shape | interface |\n| react element | element | ReactElement |\n| react node | node | ReactNode |\n| react child | ✘ | ReactChild |\n| react children | ✘ | ReactChildren |\n","funding_links":[],"categories":["Code Design","Uncategorized","Awesome React","JavaScript","React [🔝](#readme)"],"sub_categories":["Miscellaneous","Uncategorized","Tools"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgcanti%2Ftcomb-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgcanti%2Ftcomb-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgcanti%2Ftcomb-react/lists"}