Passer au contenu

Unions

Les types d’union sont très similaires aux interfaces, mais ils ne permettent pas de spécifier des champs communs entre les types (lisez-en plus ici). Les unions sont utiles pour retourner des types de données disjoints à partir d’un champ unique.

Code premier

Pour définir un type d’union GraphQL, nous devons définir des classes dont cette union sera composée. En suivant l’exemple de la documentation d’Apollo, nous allons créer deux classes. D’abord, Book :

Définition de la classe Book
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class Book {
@Field()
title: string;
}

Et ensuite Author :

Définition de la classe Author
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class Author {
@Field()
name: string;
}

Avec cela en place, enregistrez l’union ResultUnion en utilisant la fonction createUnionType exportée du paquet @nestjs/graphql :

Création de l'union ResultUnion
export const ResultUnion = createUnionType({
name: 'ResultUnion',
types: () => [Author, Book] as const,
});

Maintenant, nous pouvons référencer ResultUnion dans notre requête :

Référencer ResultUnion
@Query(returns => [ResultUnion])
search(): Array<typeof ResultUnion> {
return [new Author(), new Book()];
}

Cela va générer la partie suivante du schéma GraphQL en SDL :

type Author {
name: String!
}
type Book {
title: String!
}
union ResultUnion = Author | Book
type Query {
search: [ResultUnion!]
}

La fonction par défaut resolveType() générée par la bibliothèque extraira le type en fonction de la valeur retournée par la méthode résolveur. Cela signifie que retourner des instances de classe au lieu d’objets JavaScript littéraux est obligatoire.

Pour fournir une fonction resolveType() personnalisée, passez la propriété resolveType à l’objet d’options passé dans la fonction createUnionType(), comme suit :

Fonction resolveType personnalisée
export const ResultUnion = createUnionType({
name: 'ResultUnion',
types: () => [Author, Book] as const,
resolveType(value) {
if (value.name) {
return Author;
}
if (value.title) {
return Book;
}
return null;
},
});

Schéma premier

Pour définir une union dans l’approche schéma premier, créez simplement une union GraphQL avec SDL.

type Author {
name: String!
}
type Book {
title: String!
}
union ResultUnion = Author | Book

Ensuite, vous pouvez utiliser la fonctionnalité de génération de types (comme montré dans le chapitre de démarrage rapide) pour générer les définitions TypeScript correspondantes :

Définitions TypeScript pour Author et Book
export class Author {
name: string;
}
export class Book {
title: string;
}
export type ResultUnion = Author | Book;

Les unions nécessitent un champ __resolveType supplémentaire dans la carte du résolveur pour déterminer quel type l’union doit résoudre. Notez également que la classe ResultUnionResolver doit être enregistrée en tant que fournisseur dans n’importe quel module. Créons une classe ResultUnionResolver et définissons la méthode __resolveType.

Classe ResultUnionResolver
@Resolver('ResultUnion')
export class ResultUnionResolver {
@ResolveField()
__resolveType(value) {
if (value.name) {
return 'Author';
}
if (value.title) {
return 'Book';
}
return null;
}
}

Énumérations

Les types d’énumération sont un type spécial de scalaire qui est restreint à un ensemble particulier de valeurs autorisées (lisez-en plus ici). Cela vous permet de :

  • valider que tous les arguments de ce type sont l’une des valeurs autorisées
  • communiquer à travers le système de types qu’un champ sera toujours l’un d’un ensemble fini de valeurs

Code premier

Lors de l’utilisation de l’approche premier code, vous définissez un type d’énumération GraphQL simplement en créant une énumération TypeScript.

Définition de l'énumération AllowedColor
export enum AllowedColor {
RED,
GREEN,
BLUE,
}

Avec cela en place, enregistrez l’énumération AllowedColor en utilisant la fonction registerEnumType exportée du paquet @nestjs/graphql :

Enregistrer l'énumération AllowedColor
registerEnumType(AllowedColor, {
name: 'AllowedColor',
});

Maintenant, vous pouvez référencer AllowedColor dans nos types :

Utiliser AllowedColor dans les types
@Field(type => AllowedColor)
favoriteColor: AllowedColor;

Cela va générer la partie suivante du schéma GraphQL en SDL :

enum AllowedColor {
RED
GREEN
BLUE
}

Pour fournir une description pour l’énumération, passez la propriété description dans la fonction registerEnumType().

Enregistrer AllowedColor avec description
registerEnumType(AllowedColor, {
name: 'AllowedColor',
description: 'Les couleurs supportées.',
});

Pour fournir une description pour les valeurs de l’énumération, ou pour marquer une valeur comme obsolète, passez la propriété valuesMap, comme suit :

Décrire les valeurs de l'énumération
registerEnumType(AllowedColor, {
name: 'AllowedColor',
description: 'Les couleurs supportées.',
valuesMap: {
RED: {
description: 'La couleur par défaut.',
},
BLUE: {
deprecationReason: 'Trop bleu.',
},
},
});

Cela générera le schéma GraphQL suivant en SDL :

"""Les couleurs supportées."""
enum AllowedColor {
"""La couleur par défaut."""
RED
GREEN
BLUE @deprecated(reason: "Trop bleu.")
}

Schéma premier

Pour définir un énumérateur dans l’approche schéma premier, créez simplement une énumération GraphQL avec SDL.

enum AllowedColor {
RED
GREEN
BLUE
}

Ensuite, vous pouvez utiliser la fonctionnalité de génération de types (comme montré dans le chapitre de démarrage rapide) pour générer les définitions TypeScript correspondantes :

TypeScript pour AllowedColor
export enum AllowedColor {
RED,
GREEN,
BLUE,
}

Parfois, un backend impose une valeur différente pour une énumération en interne par rapport à l’API publique. Dans cet exemple, l’API contient RED, cependant dans les résolveurs, nous pouvons utiliser #f00 à la place (lisez-en plus ici). Pour ce faire, déclarez un objet résolveur pour l’énumération AllowedColor :

Résolveur AllowedColor interne
export const allowedColorResolver: Record<keyof typeof AllowedColor, any> = {
RED: '#f00',
};

Utilisez ensuite cet objet résolveur avec la propriété resolvers de la méthode GraphQLModule#forRoot(), comme suit :

Configurer GraphQLModule
GraphQLModule.forRoot({
resolvers: {
AllowedColor: allowedColorResolver,
},
});