仕様から:
GraphQLオブジェクトタイプ(ObjectTypeDefinition)...は、[入力として]再利用するには不適切です。オブジェクトタイプには、引数を定義するフィールドや、インターフェイスや共用体への参照を含めることができ、どちらも入力引数としての使用には適していません。 。このため、入力オブジェクトはシステム内で別のタイプになります。
これが「公式の理由」ですが、オブジェクトタイプを入力オブジェクトタイプとして使用できない、またはオブジェクトタイプを入力オブジェクトタイプとして使用できない実際的な理由はいくつかあります。
機能性
オブジェクトタイプと入力オブジェクトタイプの両方にフィールドがありますが、これらのフィールドには、スキーマによるこれらのタイプの使用方法を反映する異なるプロパティがあります。スキーマは、オブジェクトタイプのフィールドに対して引数とある種のリゾルバー関数を定義する可能性がありますが、これらのプロパティは入力コンテキストでは意味がありません(つまり、入力オブジェクトのフィールドを解決することはできません-すでに明示的な値があります) 。同様に、デフォルト値は入力オブジェクトタイプフィールドにのみ提供でき、オブジェクトタイプフィールドには提供できません。
言い換えれば、これは重複のように見えるかもしれません:
type Student {
name: String
grade: Grade
}
input StudentInput {
name: String
grade: Grade
}
ただし、オブジェクトタイプまたは入力オブジェクトタイプのいずれかに固有の機能を追加すると、動作が異なることが明確になります。
type Student {
name(preferred: Boolean): String
grade: Grade
}
input StudentInput {
name: String
grade: Grade = F
}
型システムの制限
GraphQLのタイプは、出力タイプと入力タイプにグループ化されます。
出力タイプは、GraphQLサービスによって生成された応答の一部として返される可能性のあるタイプです。入力タイプは、フィールドまたはディレクティブ引数の有効な入力であるタイプです。
これらの2つのグループ(つまり、スカラー、列挙型、リスト、および非ヌル)の間には重複があります。ただし、ユニオンやインターフェイスなどの抽象型は、入力コンテキストでは意味がなく、入力として使用することはできません。オブジェクト型と入力オブジェクト型を分離することで、入力型が期待される場所で抽象型が使用されないようにすることができます。
スキーマ設計
スキーマでエンティティを表す場合、一部のエンティティは実際にそれぞれの入力タイプと出力タイプの間で「フィールドを共有」する可能性があります。
type Student {
firstName: String
lastName: String
grade: Grade
}
input StudentInput {
firstName: String
lastName: String
grade: Grade
}
ただし、オブジェクトタイプは、非常に複雑なデータ構造をモデル化できます(実際には頻繁にモデル化します)。
type Student {
fullName: String!
classes: [Class!]!
address: Address!
emergencyContact: Contact
# etc
}
これらの構造は適切な入力に変換される場合がありますが(Studentを作成するため、アドレスを表すオブジェクトも渡します)、多くの場合、そうではありません。つまり、学生のクラスをクラスIDとセクションIDで指定する必要があります。オブジェクト。同様に、返したいが変更したくないpassword
フィールドがある場合や、その逆の場合もあります(フィールドのように)。
さらに、比較的単純なエンティティの場合でも、オブジェクトタイプとその「対応する」入力オブジェクトの間でnull可能性に関する要件が異なることがよくあります。多くの場合、フィールドが応答でも返されることを保証したいのですが、入力で必要とされるのと同じフィールドを作成したくありません。例えば、
type Student {
firstName: String!
lastName: String!
}
input StudentInput {
firstName: String
lastName: String
}
最後に、多くのスキーマでは、特定のエンティティのオブジェクトタイプと入力オブジェクトタイプの間に1対1のマッピングがないことがよくあります。一般的なパターンは、スキーマレベルの入力検証をさらに微調整するために、さまざまな操作に個別の入力オブジェクトタイプを利用することです。
input CreateUserInput {
firstName: String!
lastName: String!
email: String!
password: String!
}
input UpdateUserInput {
email: String
password: String
}
これらの例はすべて重要なポイントを示しています。入力オブジェクトタイプはオブジェクトタイプを反映している場合がありますが、ビジネス要件のために本番スキーマでそれを確認する可能性ははるかに低くなります。