idx: 存在関数
Facebookでは、GraphQLで取得したデータ構造の深くネストされた値にアクセスする必要があることがよくあります。これらの深くネストされた値にアクセスする際には、1つまたは複数の中間フィールドがヌルであることはよくあります。これらの中間フィールドがヌルになる理由は様々で、プライバシーチェックの失敗から、単にヌルが致命的でないエラーを表現する最も柔軟な方法であるという事実まであります。
残念ながら、これらの深くネストされた値へのアクセスは、現在、面倒で冗長です。
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または未定義のプロパティにアクセスした結果として生じるエラーをtry-catchします。そのようなエラーがキャッチされた場合、nullまたは未定義を返します。(そして、これがidx.jsでどのように実装されているかを見ることができます。)
実際には、すべてのネストされたプロパティアクセスをtry-catchすることは遅く、特定の種類のエラーを区別することは脆弱です。これらの欠点に対処するために、上記の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」を追加することで使用できます。