backend / graphql
Schéma et types de base (SDL)
Explication
Ce que vous allez apprendre
- Écrire un type d'objet GraphQL en SDL (Schema Definition Language) avec les scalaires natifs
- Comprendre ce que change concrètement le
!de non-nullabilité sur un champ - Distinguer les rôles de
Query,Mutationet des typesinput - Lire la notation de nullabilité des listes (
[String],[String!],[String!]!) - Documenter un schéma avec des descriptions visibles en introspection
Dans quel contexte ?
Une équipe backend démarre une nouvelle API pour une boutique en ligne. Avant d'écrire la moindre ligne de resolver en Python ou en JavaScript, elle doit se mettre d'accord avec l'équipe frontend sur la forme exacte des données : qu'est-ce qu'un Produit ? Son prix peut-il être absent ? Une catégorie est-elle obligatoire ? Le schéma SDL, écrit dans un fichier comme schema.graphql, sert de contrat écrit entre les deux équipes, avant même que le code n'existe.
D'abord, un type ressemble à une classe très simple
Un type GraphQL comme Produit liste des champs, chacun avec un type. Les types scalaires de base — Int, Float, String, Boolean, ID — couvrent la plupart des besoins ; ID est un identifiant unique sérialisé comme une chaîne, même s'il correspond à un entier en base de données.
Une fois les champs posés, il faut décider ce qui est obligatoire
C'est là qu'intervient le point d'exclamation. Un champ sans ! (comme description: String) peut renvoyer null : le client doit toujours vérifier sa présence avant de l'utiliser. Un champ avec ! (comme nom: String!) est un contrat ferme : le serveur s'engage à toujours fournir une valeur, jamais null. Si un resolver retourne null pour un champ marqué !, GraphQL considère que c'est une erreur du serveur, pas une réponse valide.
Le cas plus subtil : la nullabilité des listes
Une liste peut être nullable ou non, et ses éléments aussi, indépendamment l'un de l'autre — ce sont deux notations combinées, pas une seule.
| Notation | La liste elle-même | Les éléments de la liste |
|---|---|---|
[String] | peut être null | peuvent être null |
[String!] | peut être null | jamais null |
[String]! | jamais null (au pire, liste vide) | peuvent être null |
[String!]! | jamais null | jamais null |
Piège fréquent
Déclarer un champ trop strict (!) alors que la donnée peut légitimement manquer casse le client au premier null inattendu : toute la branche de la réponse est invalidée jusqu'au premier ancêtre nullable (ce mécanisme est détaillé dans la leçon sur la gestion des erreurs). Mieux vaut réfléchir honnêtement, dès la conception du schéma, à ce qui peut réellement être absent.
Ensuite, il faut distinguer les points d'entrée des types normaux
Query et Mutation ne sont pas des types comme les autres : ce sont les deux racines de tout schéma GraphQL. Chaque champ de Query correspond à une façon de lire des données, chaque champ de Mutation à une façon d'en écrire. Tout le reste du schéma (comme Produit) n'est atteignable qu'en partant de l'un de ces deux points d'entrée.
Il reste un problème : comment passer des arguments complexes ?
Un argument simple comme id: ID! suffit pour un identifiant, mais créer un produit demande plusieurs champs à la fois (nom, prix, catégorie...). C'est le rôle des types input : ils ressemblent aux types de sortie, mais sont réservés aux arguments, jamais retournés en réponse. Séparer input et output types évite d'exposer des champs de sortie (comme des relations calculées) là où seule une valeur brute est attendue en entrée.
Bonne pratique
Ajoute des descriptions textuelles (entre guillemets simples ou triples) directement dans le schéma, sur les types et les champs. Ces descriptions sont exposées par l'introspection et affichées automatiquement par des outils comme GraphiQL ou Apollo Studio : c'est une documentation qui ne peut jamais devenir obsolète, puisqu'elle vit dans le même fichier que la définition.
Maintenant que tu sais décrire des types, la suite logique est d'apprendre à les interroger côté client : direction la leçon sur les queries, où tu verras comment sélectionner précisément les champs, nommer tes requêtes et factoriser des sélections avec des fragments.
Commandes & code
Schéma et types de base (SDL)
# SDL = Schema Definition Language, le langage de description des types GraphQL
# Types scalaires natifs : Int, Float, String, Boolean, ID
type Produit {
id: ID! # ! signifie non-nullable (obligatoire)
nom: String!
prix: Float!
description: String # nullable : peut retourner null
enStock: Boolean!
quantite: Int!
}
# Type racine Query : point d'entrée pour TOUTES les lectures
type Query {
produit(id: ID!): Produit
produits(limite: Int = 20): [Produit!]! # liste non-nulle de Produit non-nuls
}
# Type racine Mutation : point d'entrée pour toutes les écritures
type Mutation {
creerProduit(nom: String!, prix: Float!): Produit!
}
# Type d'entrée (Input) : structure de données pour les arguments complexes
input CreerProduitInput {
nom: String!
prix: Float!
categorieId: ID!
tags: [String!]
}
type Mutation {
creerProduitAvecInput(input: CreerProduitInput!): Produit!
}Nullabilité — la règle la plus importante du typage GraphQL :
| Notation | Signification |
|---------------|---------------------------------------------------------|
| String | peut être null OU absent d'une liste, valeur optionnelle |
| String! | jamais null, valeur garantie présente |
| [String] | liste nullable d'éléments nullables |
| [String!] | liste nullable d'éléments non-nullables |
| [String!]! | liste non-nullable d'éléments non-nullables (le + strict) |# Documenter le schéma directement avec des descriptions (visibles en introspection)
"""
Représente un produit vendu sur la plateforme.
"""
type Produit {
"Identifiant unique du produit"
id: ID!
"Nom affiché au client"
nom: String!
}Résumé
- Le
!marque un champ non-nullable : le serveur DOIT toujours fournir une valeur, sinon c'est une erreur. QueryetMutationsont les seuls points d'entrée du schéma, tout le reste en découle par typage.- Les
inputtypes structurent les arguments complexes, séparés des types de sortie. - Bien réfléchir la nullabilité dès le schéma : un champ trop strict casse le client au premier null inattendu.
Exercices pratiques
Mission : corriger un schéma SDL mal pensé avant l'intégration frontend
Objectif : Repérer une erreur de nullabilité dans le type Produit et concevoir correctement un nouveau champ de liste avant que l'équipe frontend ne commence l'intégration.
Contexte
Le schéma actuel déclare description: String! sur Produit. En pratique, les produits fraîchement importés depuis le fournisseur n'ont pas encore de description rédigée par l'équipe marketing. L'équipe frontend n'a pas encore commencé l'intégration : c'est le bon moment pour corriger le schéma, avant que quiconque ne s'appuie sur ce contrat cassé.