propTypesプロパティに指定できる型
prop-typesライブラリの概要については把握できたかと思うので、本項では実際にどんな形で型情報を表現できるのかを紹介していきます。
基本型
まず、JavaScriptのプリミティブ型に対応するものとして、次の型が用意されています。
| 型 | 意味 |
|---|---|
| PropTypes.array | 配列型(要素の型は問わない) |
| PropTypes.bool | 真偽値型 |
| PropTypes.func | 関数型 |
| PropTypes.number | 数値型 |
| PropTypes.object | オブジェクト型(内部の構造は問わない) |
| PropTypes.string | 文字列型 |
| PropTypes.symbol | シンボル型(※注1) |
※注1:シンボル型はES6で導入されたデータ型で、絶対に他の値とかぶらないユニークな値を生成することができます。
array型とobject型については内部の型を問わないため、厳密な型定義をしたくない場合に有用です。
また、少し特殊な型として、次の3つが用意されています。
| 型 | 意味 |
|---|---|
| PropTypes.element | React Element(childrenなど) |
| PropTypes.node | 数値型、文字列型、Elementのいずれか(またはその配列) |
| PropTypes.any | なんでもいい |
elementはJSXを渡す場合に使用します。
anyは上で紹介したすべての型を受け付けることができるワイルドカードです。あまり使うことはないでしょう。
複雑な型
それでは、基本型を組み合わせて複雑な型を表現するための機能について見ていきましょう。
| 型 | 意味 |
|---|---|
| PropTypes.instanceOf(HogeClass) | HogeClass型のクラスのインスタンスである |
| PropTypes.oneOf(['A', 'B', 'C']) | 配列内のいずれかの値である |
| PropTypes.oneOfType([T1, T2, ...]) | 配列内のいずれかの型である(配列内はPropTypes.stringなどの型) |
| PropTypes.arrayOf(T) | T型の要素を持つ配列である(TはPropTypes.stringなどの型) |
| PropTypes.objectOf(T) | T型のプロパティを持つオブジェクトである(TはPropTypes.stringなどの型) |
| PropTypes.shape({ t1: T1, t2: T2, ... }) | プロパティ名と型を組み合わせて定義する |
これらのうちList.propTypesの例で扱った、oneOf、arrayOf、shapeの3つは非常に汎用性が高いので、ぜひ活用してください。
必須の型
あるプロパティが必要な場合は、末尾にisRequiredを付与することで表現できます。
Hoge.propTypes = {
name: PropTypes.string.isRequired, // 文字列型(必須)
address: PropTypes.string // 文字列型(渡さなくてもいい)
}
この例の場合、Hogeコンポーネントにはname属性のみを渡しても問題ありません。
実例で見てみる
さて、PropTypesモジュールが提供する型が一通り分かったところで、前述のListコンポーネントのpropTypesプロパティの定義がどのようなものだったか、もう一度確認してみましょう。
まず、postsは配列です。配列はPropTypes.arrayOfでしたね。
posts: PropTypes.arrayOf(...)
arrayOfの引数には型を渡すことになるわけですが、postsの中身は単純なnumberやstringではなく「name, age, body」という3つのプロパティを持つオブジェクトの配列でした。単に「オブジェクトです」と言いたいだけであれば PropTypes.arrayOf(PropTypes.object) でも構わないわけですが、今回はちゃんとプロパティが3つともそろっているか確かめたかったので、PropTypes.shapeを使うことにしました。
posts: PropTypes.arrayOf(
PropTypes.shape({
name: ...,
age: ...,
body: ...
})
)
> nameとbodyは文字列で必須項目なので、PropTypes.string.isRequiredでOKですね。
posts: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string.isRequired,
age: ...,
body: PropTypes.string.isRequired
})
)
さて、最後にageですが、これは"teen"、"twenties"、"thirties"、"fourties"、"fifties"のいずれかひとつの値を取る必須項目でした。いずれかの値を取るということで、PropTypes.oneOfを使います。
posts: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string.isRequired,
age: PropTypes.oneOf([
"teen",
"twenties",
"thirties",
"fourties",
"fifties"
]).isRequired,
body: PropTypes.string.isRequired
})
)
これで、複雑なデータ型を持つpostsに対して、propTypesプロパティを定義することができました。oneOf、arrayOf、shapeは本当に有用で、これと基本型を組み合わせれば大抵のデータ型は表現でます。ぜひ覚えておきましょう。
