Need help with tcomb-react?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

gcanti
201 Stars 13 Forks MIT License 125 Commits 3 Opened issues

Description

Alternative syntax for PropTypes

Services available

!
?

Need anything else?

Contributors list

No Data

build status dependency status npm downloads

Features

  • by default props are required, a saner default since it's quite easy to forget
    .isRequired
  • checks for unwanted additional props
  • documentation (types and comments) can be automatically extracted
  • additional fine grained type checks, nestable at arbitrary level
  • builds on tcomb, tcomb-validation, tcomb-doc libraries

Compatibility

tcomb-react
has been tested and found working on the following targets. The list is not exhaustive and
tcomb-react
will probably work on other versions that haven't been listed.

React:

^0.13.0
,
^0.14.0
,
^15.0.0

Prop types

The
@props
decorator (ES7)

For an equivalent implementation in ES5, or for Stateless Components, see the

propTypes
function below.

Signature

type Props = {[key: string]: TcombType};

type PropsType = TcombStruct | TcombInterface;

type Type = Props | PropsType | Refinement;

type Options = { strict?: boolean // default true };

@props(type: Type, options?: Options)

where

  • type
    can be a map
    string -> TcombType
    , a
    tcomb
    struct, a
    tcomb
    interface, a refinement of a
    tcomb
    struct / interface, a refinement of a
    tcomb
    interface
  • options
    :
    • strict: boolean
      (default
      true
      ) if
      true
      checks for unwanted additional props

Example (ES7)

import t from 'tcomb'
import { props } from 'tcomb-react'

const Gender = t.enums.of(['Male', 'Female'], 'Gender') const URL = t.refinement(t.String, (s) => s.startsWith('http'), 'URL')

@props({ name: t.String, // a required string surname: t.maybe(t.String), // an optional string age: t.Number, // a required number gender: Gender, // an enum avatar: URL // a refinement }) class Card extends React.Component {

render() { return (

{this.props.name}

...
) }

}

Unwanted additional props

By default

tcomb-react
checks for unwanted additional props:
@props({
  name: t.String
})
class Person extends React.Component {

render() { return (

{this.props.name}

) }

}

...

Output

Warning: Failed propType: [tcomb] Invalid additional prop(s):

[ "surname" ]

supplied to Person.

Note. You can opt-out passing the

option
argument
{ strict: false }
.

The
propTypes
function

Signature

Same as

@props
.

Stateless Component Example

import { propTypes } from 'tcomb-react'

const MyComponentProps = t.interface({ name: t.String, });

const MyComponent = (props) => (

); MyComponent.propTypes = propTypes(MyComponentProps);

ES5

React.createClass
Example

var t = require('tcomb');
var propTypes = require('tcomb-react').propTypes;

var Gender = t.enums.of(['Male', 'Female'], 'Gender'); var URL = t.refinement(t.String, function (s) { return s.startsWith('http'); }, 'URL');

var Card = React.createClass({

propTypes: propTypes({ name: t.String, // a required string surname: t.maybe(t.String), // an optional string age: t.Number, // a required number gender: Gender, // an enum avatar: URL // a refinement }),

render: function () { return (

{this.props.name}

...
); }

});

How it works

The

@props
decorator sets
propTypes
on the target component to use a custom validator function built around tcomb types for each specified prop.

For example, the following:

const URL = t.refinement(t.String, (s) => s.startsWith('http'), 'URL');

@props({ name: t.String, url: URL, }) class MyComponent extends React.Component { // ... }

is roughly equivalent to:

const URL = t.refinement(t.String, (s) => s.startsWith('http'), 'URL');

class MyComponent extends React.Component { // ... } MyComponent.propTypes = { name: function(props, propName, componentName) { if (!t.validate(props[propName], t.String).isValid()) { return new Error('...'); } }, url: function(props, propName, componentName) { if (!t.validate(props[propName], URL).isValid()) { return new Error('...'); } }, }

The babel plugin

Using babel-plugin-tcomb you can express

propTypes
as Flow type annotations:
import React from 'react'
import ReactDOM from 'react-dom'
import type { $Refinement } from 'tcomb'
import { props } from 'tcomb-react'

type Gender = 'Male' | 'Female';

const isUrl = (s) => s.startsWith('http') type URL = string & $Refinement;

type Props = { name: string, surname: ?string, age: number, gender: Gender, avatar: URL };

@props(Props) class Card extends React.Component {

render() { return (

{this.props.name}

...
) }

}

Extract documentation from your components

The
parse
function

Given a path to a component file returns a JSON / JavaScript blob containing props types, default values and comments.

Signature

(path: string | Array) => Object

Example

Source

import t from 'tcomb'
import { props } from 'tcomb-react'

/**

  • Component description here
  • @param name - name description here
  • @param surname - surname description here
  • /

@props({ name: t.String, // a required string surname: t.maybe(t.String) // an optional string }) export default class Card extends React.Component {

static defaultProps = { surname: 'Canti' // default value for surname prop }

render() { return (

{this.props.name}

{this.props.surname}

) } }

Usage

import parse from 'tcomb-react/lib/parse'
const json = parse('./components/Card.js')
console.log(JSON.stringify(json, null, 2))

Output

{
  "name": "Card",
  "description": "Component description here",
  "props": {
    "name": {
      "kind": "irreducible",
      "name": "String",
      "required": true,
      "description": "name description here"
    },
    "surname": {
      "kind": "irreducible",
      "name": "String",
      "required": false,
      "defaultValue": "Canti",
      "description": "surname description here"
    }
  }
}

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).

Parsing multiple components

import parse from 'tcomb-react/lib/parse'
import path from 'path'
import glob from 'glob'

function getPath(file) { return path.resolve(process.cwd(), file); }

parse(glob.sync('./components/*.js').map(getPath));

The
toMarkdown
function

Given a JSON / JavaScript blob returned by

parse
returns a markdown containing the components documentation.

Signature

(json: Object) => string

Example

Usage

import parse from 'tcomb-react/lib/parse'
import toMarkdown from 'tcomb-react/lib/toMarkdown'
const json = parse('./components/Card.js')
console.log(toMarkdown(json));

Output

## Card

Component description here

Props

  • name: String name description here
  • surname: String (optional, default: "Canti") surname description here

Augmented pre-defined types

tcomb-react
exports some useful pre-defined types:
  • ReactElement
  • ReactNode
  • ReactChild
  • ReactChildren

Example

import { props, ReactChild } from 'tcomb-react';

@props({ children: ReactChild // only one child is allowed }) class MyComponent extends React.Component {

render() { return (

{this.props.children}
); }

}

Support for babel-plugin-tcomb

The following types for Flow are exported:

  • ReactElementT
  • ReactNodeT
  • ReactChildT
  • ReactChildrenT

Comparison table

| Type | React | tcomb-react | |------|-------|-------------| | array | array | Array | | boolean | bool | Boolean | | functions | func | Function | | numbers | number | Number | | objects | object | Object | | strings | string | String | | all | any | Any | | required prop | T.isRequired | T | | optional prop | T | maybe(T) | | custom types | ✘ | ✓ | | tuples | ✘ | tuple([T, U, ...]) | | lists | arrayOf(T) | list(T) | | instance | instanceOf(A) | T | | dictionaries | objectOf(T) | dict(T, U) (keys are checked) | | enums | oneOf(['a', 'b']) | enums.of('a b') | | unions | oneOfType([T, U]) | union([T, U]) | | duck typing | shape | interface | | react element | element | ReactElement | | react node | node | ReactNode | | react child | ✘ | ReactChild | | react children | ✘ | ReactChildren |

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.