flowの$PropertyTypeと$ElementTypeの違い
型定義したファイルをimportして使うときの話
$PropertyType
JavaScriptでflowを使って型を定義する場合、 型の定義自体は別ファイルで行いそれをimportして使うことができます
例えばReactで本の情報を登録する画面を作ろうと思い、 本のid、タイトル、著者名をstateで管理します
以下のようなディレクトリ構成の場合
javascript component books.js type book.js
type/book.jsで肩を定義し
// type/book.js // @flow type Book = {| id: number, title: string, author: string, |}; export default Book;
component/books.jsで読み込んで使います
// component/books.js // @flow import { Book } from '../type/book'; type State = {| id: $PropertyType<Book, 'id'>, title: $PropertyType<Book, 'title'>, author: $PropertyType<Book, 'author'> |}
上のように$PropertyType
を使うとすでに定義してあるBook typeの
idやtitleを使用しているということをわかりやすく書くことができます
$ElementType
ただ毎度毎度$PropertyType
と書くのも数が少ないうちはいいですが増えていくとかなり見辛くなります
先輩に $EntityType
使って書いた方が見やすいよと言われました
さっきのコードを書き直すと下のようになります
// component/books.js // @flow import { Book } from '../type/book'; type BET<k> = $ElementType<Book, k>; type State = {| id: BET<'id'>, title: BET<'title'>, author: BET<author'> |}
さっきまでわざわざ $PropertyTypeって書いてたところを自分で命名できるのでかなり見やすくなりました
でもこの二つって何が違うんでしょう?
$PropertyTypeと$EntityTypeの違い
時間があるひとは公式を見てください
flowの公式でも$ElementTypeの説明にこう書いてあります
we’re using literal values as K, similarly to $PropertyType<T, k>. However, when using $ElementType<T, K>, K is allowed to be any type, as long as that type exists on the keys of T.
$ElementTypeを使用する場合は、第一引数に定義した型のkeyとして存在するものならなんでも 第二引数に渡すことができます
じゃあ$PropertyTypeはどうなんでしょう? $PropertyTypeを使って
type BET<k> = $PropertyType<Book, k>;
と書くと以下のようなerrorが出ます
Cannot use `$PropertyType` because the second type argument must be a string literal.
$PropertyTypeは第二引数に文字列しか許してくれないので、上の例のように型がわからないkを渡した時点でエラーが出ます $ElementTypeは実際に使用されて、kに入ってきた値がkeyとして存在しないとわかったタイミングでエラーになります
ElementTypeの方が使い勝手良さそうだなあ、、、