Détail du package

tcomb-react

gcanti52.5kMIT0.9.3

Type checking for React components

tcomb, react, react-component

readme

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

React: ^0.13.0, ^0.14.0, ^15.0.0

Prop types

The @props decorator (ES7)

For an equivalent implementation in ES5 see the propTypes function below.

Signature

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

type PropsType = TcombStruct | TcombInterface;

type Type = Props | PropsType | Refinement<PropsType>;

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, 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 (
      <div>
        <p>{this.props.name}</p>
        ...
      </div>
    )
  }

}

Unwanted additional props

By default tcomb-react checks for unwanted additional props:

@props({
  name: t.String
})
class Person extends React.Component {

  render() {
    return (
      <div>
        <p>{this.props.name}</p>
      </div>
    )
  }

}

...

<Person name="Giulio" surname="Canti" />

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 (ES5)

Signature

Same as @props.

Example (ES5)

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 (
      <div>
        <p>{this.props.name}</p>
        ...
      </div>
    );
  }

});

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<typeof isUrl>;

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

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

  render() {
    return (
      <div>
        <p>{this.props.name}</p>
        ...
      </div>
    )
  }

}

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<string>) => 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 (
      <div>
        <p>{this.props.name}</p>
        <p>{this.props.surname}</p>
      </div>
    )
  }
}

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 requireable 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 (
      <div>
        {this.props.children}
      </div>
    );
  }

}

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 struct
react element element ReactElement
react node node ReactNode
react child ReactChild
react children ReactChildren

changelog

Changelog

Tags:

  • [New Feature]
  • [Bug Fix]
  • [Breaking Change]
  • [Documentation]
  • [Internal]
  • [Polish]
  • [Experimental]

Note: Gaps between patch versions are faulty/broken releases.

v0.9.3

  • New Feature
    • support all tcomb types, fix #40 (@gcanti)

v0.9.2

  • Experimental
    • add support for babel-plugin-tcomb, fix #32 (@gcanti)
    • the following exports and augmentations are deprecated:
      • t
      • t.ReactElement
      • t.ReactNode
      • t.ReactChild
      • t.ReactChildren

v0.9.1

  • New Feature
    • account for interfaces (tcomb ^3.1.0)

v0.9.0

Warning. If you don't rely in your codebase on the property maybe(MyType)(undefined) === null this is not a breaking change for you.

  • Breaking Change
    • upgrade to tcomb-doc v0.5.0
    • upgrade to tcomb-validation v3.0.0

v0.8.13

  • Bug Fix
    • t.ReactChildren rejects a correctly renderable children, fix #29 (thanks @FrancescoCioria)

v0.8.12

  • New Feature
    • Documentation tool: parse module, fix #24
    • Documentation tool: toMarkdown module, fix #25

v0.8.11

  • New Feature
    • attach the original predicate to propTypes.__subtype__.predicate so other components can read it
  • Internal
    • upgrade to latest tcomb-validation (2.2.0)
    • add tests for production env

v0.8.10

  • New Feature
    • ReactChild and ReactChildren pre-defined types, fix #19 (thanks @jedmao)

v0.8.9

  • Internal
    • upgrade to react v0.14.0-rc1

v0.8.8

  • New Feature
    • additional argument options to propType() to allow a finer configuration

v0.8.7

  • New Feature
    • Added support for childContextTypes and contextTypes (thanks @gavacho)

v0.8.6

  • New Feature
    • added pre-defined types (#14):
      • t.ReactElement
      • t.ReactNode
    • ReactElement and ReactNode at top level are deprecated

v0.8.5

  • New Feature
    • added pre-defined types (#14):
      • ReactElement
      • ReactNode

v0.8.4

  • Internal
    • upgrade to latest version of tcomb-validation (2.0.0)

v0.8.3

  • New Feature
    • re-export tcomb

v0.8.2

  • New Feature
    • propTypes can also accept an object fix #12 (thanks @tehnomaag)

v0.8.1

  • New Feature (thanks @deoxxa)
    • show all the errors from tcomb-validation in warnings
    • report all additional properties, not just the first
    • retain (limited) proptypes in production

v0.8.0

  • Breaking Change
    • upgrade to tcomb-validation v2.0

v0.5.0

  • New Feature
    • If you try to pass additional props it will fail

v0.4.0

  • New Feature
    • Add @props ES7 decorator
  • Breaking Change
    • Remove react and t namespace
    • Remove ReactElement and ReactNode type
    • Remove React dependency

v0.3.0

  • Internal
    • Upgrade to latest tcomb-validation
    • Remove tcomb-form and react-tools dependencies #7
  • Polish
    • Remove Playground [BREAKING]

v0.2.4

  • New Feature
    • make propTypes introspectable by adding a tcomb property #6

v0.2.3

  • Bug Fix
    • fix a bug when propTypes is a subtype

v0.2.2

  • Polish
    • move tcomb-validation and tcomb-form to peerDependencies, fix #5
    • update to tcomb-form v0.4.5

v0.2.1

  • Polish
    • update to tcomb-form v0.4.2

v0.2.0

  • Internal
    • complete refactoring