メインコンテンツへスキップ

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;

最後に、idx のカスタム Flow 型宣言を追加しました。これにより、2番目の引数内の走査が適切に型チェックされつつ、ヌル許容プロパティへのネストされたアクセスが許可されます。

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