185 votes

Quel est l'intérêt du type d'entrée dans GraphQL ?

Pourriez-vous expliquer pourquoi, si l'argument d'entrée de la mutation est un objet, il devrait être type de saisie ? Je pense que c'est beaucoup plus simple : il suffit de réutiliser type sans fournir d'identification.

Par exemple :

type Sample {
  id: String
  name: String
}

input SampleInput {
  name: String
}

type RootMutation {
  addSample(sample: Sample): Sample  # <-- instead of it should be
  addSample(sample: SampleInput): Sample
}

C'est correct pour les petits objets, mais lorsque vous avez beaucoup d'objets avec plus de 10 propriétés dans le schéma, cela devient un fardeau.

60 votes

Les objets d'entrée doivent être sérialisables. Comme les objets de sortie peuvent contenir des cycles, ils ne peuvent pas être réutilisés pour les entrées.

2 votes

Jesse, il semble que la réponse soit suffisante ! Vous pouvez répondre et je le marque ainsi.

0 votes

Je me demande s'il est possible de combiner des interfaces avec celui-ci.

255voto

Daniel Rearden Points 8834

De la spécification :

Le type d'objet GraphQL (ObjectTypeDefinition)... ne peut pas être réutilisé [en tant qu'entrée], car les types d'objet peuvent contenir des champs qui définissent des arguments ou contiennent des références à des interfaces et des unions, ce qui n'est pas approprié pour une utilisation en tant qu'argument d'entrée. Pour cette raison, les objets d'entrée ont un type distinct dans le système.

C'est la "raison officielle", mais il y a plusieurs raisons pratiques pour lesquelles vous ne pouvez pas utiliser un type d'objet comme type d'objet d'entrée ou utiliser un type d'objet comme type d'objet d'entrée :

Fonctionnalité

Les types d'objets et les types d'objets d'entrée ont tous deux des champs, mais ces champs ont des propriétés différentes qui reflètent la façon dont ces types sont utilisés par le schéma. Votre schéma définira potentiellement des arguments et une sorte de fonction de résolution pour les champs d'un type d'objet, mais ces propriétés n'ont pas de sens dans un contexte d'entrée (c'est-à-dire que vous ne pouvez pas résoudre un champ d'un objet d'entrée -- il a déjà une valeur explicite). De même, les valeurs par défaut ne peuvent être fournies que pour les champs de type objet d'entrée, et non pour les champs de type objet.

En d'autres termes, cela peut sembler faire double emploi :

type Student {
  name: String
  grade: Grade
}

input StudentInput {
  name: String
  grade: Grade
}

Mais l'ajout de fonctionnalités spécifiques aux types d'objets ou aux types d'objets d'entrée montre clairement qu'ils se comportent différemment :

type Student {
  name(preferred: Boolean): String
  grade: Grade
}

input StudentInput {
  name: String
  grade: Grade = F
}

Limites du système de type

Les types dans GraphQL sont regroupés en types de sortie et types de saisie .

Les types de sortie sont des types qui peuvent être retournés dans le cadre d'une réponse produite par un service GraphQL. Les types d'entrée sont des types qui sont des entrées valides pour les arguments des champs ou des directives.

Il y a un chevauchement entre ces deux groupes (c'est-à-dire scalaires, enums, listes et non-nulls). Cependant, types abstraits comme les unions et les interfaces n'ont pas de sens dans un contexte d'entrée et ne peuvent pas être utilisées comme entrées. La séparation des types d'objets et des types d'objets d'entrée vous permet de vous assurer qu'un type abstrait n'est jamais utilisé là où un type d'entrée est attendu.

Conception des schémas

Lorsque vous représentez une entité dans votre schéma, il est probable que certaines entités "partagent des champs" entre leurs types d'entrée et de sortie respectifs :

type Student {
  firstName: String
  lastName: String
  grade: Grade
}

input StudentInput {
  firstName: String
  lastName: String
  grade: Grade
}

Cependant, les types d'objets peuvent modéliser (et le font souvent en réalité) des structures de données très complexes :

type Student {
  fullName: String!
  classes: [Class!]!
  address: Address!
  emergencyContact: Contact
  # etc
}

Bien que ces structures mai Si les données sont souvent traduites par des entrées appropriées (nous créons un étudiant, nous transmettons donc également un objet représentant son adresse), ce n'est souvent pas le cas -- par exemple, nous avons peut-être besoin de spécifier les classes de l'étudiant par l'ID de classe et l'ID de section, et non par un objet. De même, nous pouvons avoir des champs que nous voulons renvoyer, mais que nous ne voulons pas modifier, ou vice versa (comme un objet password ).

En outre, même pour des entités relativement simples, nous avons souvent des exigences différentes en matière de nullité entre les types d'objets et leurs objets d'entrée "équivalents". Souvent, nous voulons garantir qu'un champ sera également renvoyé dans une réponse, mais nous ne voulons pas rendre ces mêmes champs obligatoires dans notre entrée. Par exemple,

type Student {
  firstName: String!
  lastName: String!
}

input StudentInput {
  firstName: String
  lastName: String
}

Enfin, dans de nombreux schémas, il n'y a souvent pas de correspondance biunivoque entre le type d'objet et le type d'objet d'entrée pour une entité donnée. Un modèle commun consiste à utiliser des types d'objets d'entrée distincts pour différentes opérations afin d'affiner la validation des entrées au niveau du schéma :

input CreateUserInput {
  firstName: String!
  lastName: String!
  email: String!
  password: String!
}

input UpdateUserInput {
  email: String
  password: String
}

Tous ces exemples illustrent un point important : si un type d'objet d'entrée peut parfois refléter un type d'objet, il est beaucoup moins probable que cela se produise dans les schémas de production en raison des exigences commerciales.

29voto

LB2 Points 2949

Le commentaire de Jesse est correct. Pour une réponse plus formelle, voici l'extrait de Documentation GraphQL sur les types d'entrée :

Le type Object défini ci-dessus ne peut être réutilisé ici, car les Objects peuvent contenir des champs qui expriment des références circulaires ou ou des références à des interfaces et des unions, ce qui n'est pas approprié pour une utilisation en tant qu'argument d'entrée. Pour cette raison, les objets d'entrée ont un type distinct dans le système.

UPDATE

Depuis que je l'ai posté, j'ai découvert que les références circulaires sont en fait acceptables, tant qu'elles sont nilables (sinon cela déclarerait une chaîne infinie). Mais, il y a encore d'autres limitations (par exemple les interfaces) qui semblent nécessiter un système de type séparé pour les entrées.

5 votes

Il y a un peu plus de discussion ici sur la raison pour laquelle cette restriction existe : github.com/graphql/graphql-js/issues/599

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X