Quick post that documents the various quirks of `propTypes`.
The React `propTypes` semantics differ from the ones from Flow and can cause subtle bugs. Here’s a handy cheat sheet.
PropTypes
propTypes: {
// field required, must be number and NOT `null` NOR `undefined`
foo: PropTypes.number.isRequired
}
propTypes: {
// field can be omitted; if provided, can be number OR `null` OR `undefined`
foo: PropTypes.number
}
This is unfortunate, because there’s no easy way to express the followings:
- Mandatory `foo`, but with a nullable value.
- Optional `foo`, but if passed, should NOT be nullable.
Things get more complicated when we add `defaultProps`:
getDefaultProps: {
foo: 1
}
// foo: PropTypes.number.isRequired
<Comp foo={undefined} /> // foo = 1
<Comp /> // foo = 1
<Comp foo={null} /> // propTypes warning! Tells you that it's `null`
// foo: PropTypes.number
<Comp foo={undefined} /> // foo = 1
<Comp /> // foo = 1
<Comp foo={null} /> // foo = null
Some of the cases above can screw us up.
What about Flow?
props: {
foo?: number // field can be absent, but if passed, must be a number
}
props: {
foo: ?number // mandatory field, either number or null
}
props: {
foo?: ?number // optional field, whose value, if ever passed, can be null
}
props: {
foo: number // mandatory number
}
Works as expected with defaultProps too. Though in Flow, `?number` accepts `number`, `null`, and `undefined` (edit: thanks to James Kyle and Forbes Lindesay for the corrections!).
In an ideal world with Flow we’ll drop `propTypes`; for now, use it carefully in conjunction with `defaultProps`, `null`, `undefined` and optional fields.
(Use Flow)