はじめに
フロントエンド開発でGraphQLを使っているプロジェクトは多いと思いますが、以前はFragmentで定義された部分の型定義の方法がわからず、型アサーションを使用して無理やり型定義していました。しかし、GraphQLにはuseFragmentという機能があり、これを使うことで、型アサーションを用いるよりもずっと型安全にデータの型を定義できます。なので今回はuseFragmentについて記述していきます。
そもそもuseFragmentとは
useFragmentは、Reactアプリケーション内でGraphQLフラグメントを効果的に利用するためのhookです。
そもそもGraphQLのFragmentとは、クエリ内で再利用可能なデータの塊を定義するための機能で、コードの重複を避け、データ要求をより明確に管理するのに役立ちます。難しいこと書いてるけど要は共通化ということです。
Fragmentを使用すると、異なるQueryやMutation間で同じデータ構造を要求する際に、その定義を一箇所にまとめることができ、結果としてアプリケーション全体での一貫性とメンテナンス性が向上します。
useFragmentを使用すると、Fragmentを通じて取得したデータをコンポーネント内で直接利用でき、TypeScriptと組み合わせることで、取得したデータの型を正確に推測し、型安全性を高めることができます。これにより、型アサーションに頼る必要がなくなります。
なぜ型アサーションがよくないのか
型アサーションは、型システムの一部を一時的にオーバーライドする方法です。TypeScriptのような静的型付け言語では、型アサーションを使用して、ある変数が特定の型を持つと「断言」することができます。これは一見便利に思えますが、実際には型安全性を損ね、エラーを見逃す原因となることがあります。
型アサーションの問題点
例えば下記のようなコードがあったとします。
// GraphQLから取得したデータ
const userData = fetchUserData() as User;
// User型のオブジェクトとしてuserDataを扱う
// nameなんてfieldないのにコンパイル時にはエラーが出ないので気付けない
console.log(userData.name);
ここでfetchUserData関数が返すデータの型がUserと完全に一致しない場合、ランタイムでエラーが発生する可能性があります。しかし、型アサーションを使用することで、コンパイル時にはエラーが発生しないため、問題が見過ごされることになります。つまり、全く型が保証されていないということです。
型アサーションのもう一つの問題は、コードの可読性と保守性に影響を及ぼすことです。型アサーションを多用することで、実際の型と想定する型の間に齟齬が生じ、後からコードを読む人が混乱する原因となります。
useFragmentを使うことの利点
useFragmentを使用する場合、GraphQLのフラグメントを通じてデータを取得し、その型を自動的に推論させることができます。これにより、型アサーションを避け、より型安全な方法でデータを扱うことが可能になります。以下はuseFragmentを使用した場合の例です。
import { graphql, useFragment } from 'react-relay';
const userDataFragment = graphql`
fragment UserData on User {
name
email
}
`;
function UserProfile({ userDataRef }) {
const userData = useFragment(userDataFragment, userDataRef);
// userDataはUser型として正しく推論される
console.log(userData.name, userData.email);
}
このように、useFragmentを使用することで、Fragmentの型を正確に推論し、型アサーションに頼ることなくデータを安全に扱うことができます。
最後に
型は優しくて丁寧に安全に定義しよう。