本文へ移動

idx: 存在関数

·読了時間2分
Timothy Yung
Facebook エンジニアリングマネージャー

Facebookでは、GraphQLで取得したデータ構造内の深くネストされた値にアクセスする必要があることがよくあります。これらの深くネストされた値にアクセスする際に、1つ以上の中間フィールドがnull許容であることは一般的です。これらの中間フィールドがnullになる理由は様々で、プライバシーチェックの失敗から、nullが非致命的エラーを表す最も柔軟な方法であるという事実まで様々です。

残念ながら、現在これらの深くネストされた値へのアクセスは面倒で冗長です。

props.user &&
props.user.friends &&
props.user.friends[0] &&
props.user.friends[0].friends;

これをはるかに便利にする存在演算子を導入するECMAScriptの提案があります。しかし、その提案が確定するまで、生活の質を向上させ、既存の言語セマンティクスを維持し、Flowによる型安全性を促進するソリューションが必要です。

私たちは、idxと呼ぶ存在*関数*を考案しました。

idx(props, _ => _.user.friends[0].friends);

このコードスニペットの呼び出しは、上のコードスニペットのブール式と同様に動作しますが、繰り返し回数が大幅に少なくなっています。idx関数は正確に2つの引数を取ります。

  • 任意の値(通常はオブジェクトまたは配列)で、ネストされた値にアクセスしたい値です。
  • 最初の引数を受け取り、その上でネストされた値にアクセスする関数。

理論的には、idx関数はnullまたはundefinedのプロパティにアクセスすることによって発生するエラーをtry-catchします。このようなエラーがキャッチされた場合、nullまたはundefinedを返します。(そして、これがどのように実装されているかはidx.jsで確認できます。)

実際には、すべてのネストされたプロパティアクセスをtry-catchすることは遅く、特定の種類のTypeErrorを区別することは脆いです。これらの欠点を解決するために、上記のidx呼び出しを次の式に変換するBabelプラグインを作成しました。

props.user == null
? props.user
: props.user.friends == null
? props.user.friends
: props.user.friends[0] == null
? props.user.friends[0]
: props.user.friends[0].friends;

最後に、null許容プロパティへのネストされたアクセスを許可しながら、2番目の引数でのトラバーサルを適切に型チェックできるidxのカスタムFlow型宣言を追加しました。

この関数、Babelプラグイン、Flow宣言は現在GitHubで公開されています。**idx**と**babel-plugin-idx**のnpmパッケージをインストールし、`.babelrc`ファイルのプラグインリストに「idx」を追加することで使用できます。