GraphQL4 min read

Unionlar

Union turlari interfeyslarga juda o'xshaydi, ammo ular turlar orasida umumiy maydonlarni belgilay olmaydi (batafsil here). Unionlar bitta maydondan o'zaro kesishmaydigan ma'lumot t

Union turlari interfeyslarga juda o'xshaydi, ammo ular turlar orasida umumiy maydonlarni belgilay olmaydi (batafsil here). Unionlar bitta maydondan o'zaro kesishmaydigan ma'lumot turlarini qaytarishda foydali.

Code first yondashuvi

GraphQL union turini aniqlash uchun bu union tarkibini tashkil etadigan klasslarni belgilashimiz kerak. Apollo hujjatlaridagi example asosida ikki klass yaratamiz. Avval Book:

TypeScript
1import { Field, ObjectType } from '@nestjs/graphql';
2
3@ObjectType()
4export class Book {
5  @Field()
6  title: string;
7}

Keyin Author:

TypeScript
1import { Field, ObjectType } from '@nestjs/graphql';
2
3@ObjectType()
4export class Author {
5  @Field()
6  name: string;
7}

Shu bilan, @nestjs/graphql paketidan eksport qilinadigan createUnionType funksiyasi orqali ResultUnion unionini ro'yxatdan o'tkazing:

TypeScript
1export const ResultUnion = createUnionType({
2  name: 'ResultUnion',
3  types: () => [Author, Book] as const,
4});
Warning

createUnionType funksiyasining types propertysi qaytargan massivga const assertion berilishi kerak. Agar const assertion berilmasa, kompilyatsiya vaqtida noto'g'ri deklaratsiya fayli generatsiya qilinadi va uni boshqa loyihadan ishlatganda xato yuz beradi.

Endi biz so'rovda ResultUnionni ko'rsatishimiz mumkin:

TypeScript
1@Query(() => [ResultUnion])
2search(): Array<typeof ResultUnion> {
3  return [new Author(), new Book()];
4}

Bu SDL formatida GraphQL sxemasining quyidagi qismini generatsiya qiladi:

Graphql
1type Author {
2  name: String!
3}
4
5type Book {
6  title: String!
7}
8
9union ResultUnion = Author | Book
10
11type Query {
12  search: [ResultUnion!]!
13}

Kutubxona yaratadigan standart resolveType() funksiyasi type ni resolver metodidan qaytarilgan qiymat asosida aniqlaydi. Bu, literal JavaScript obyektlar emas, balki klass instansiyalarini qaytarish majburiyligini anglatadi.

Moslashtirilgan resolveType() funksiyasini berish uchun createUnionType() funksiyasiga uzatiladigan options obyektiga resolveType propertysini quyidagicha kiriting:

TypeScript
1export const ResultUnion = createUnionType({
2  name: 'ResultUnion',
3  types: () => [Author, Book] as const,
4  resolveType(value) {
5    if (value.name) {
6      return Author;
7    }
8    if (value.title) {
9      return Book;
10    }
11    return null;
12  },
13});

Schema first yondashuvi

Schema first yondashuvida unionni aniqlash uchun SDL bilan GraphQL union yarating.

Graphql
1type Author {
2  name: String!
3}
4
5type Book {
6  title: String!
7}
8
9union ResultUnion = Author | Book

So'ng, mos TypeScript ta'riflarini yaratish uchun tiplashlarni generatsiya qilish funksiyasidan foydalanishingiz mumkin (bu quick start bobida ko'rsatilgan):

TypeScript
1export class Author {
2  name: string;
3}
4
5export class Book {
6  title: string;
7}
8
9export type ResultUnion = Author | Book;

Unionlar resolver map ichida union qaysi turga yechilishini aniqlash uchun qo'shimcha __resolveType maydonini talab qiladi. Shuningdek, ResultUnionResolver klassi har qanday modulda provider sifatida ro'yxatdan o'tkazilishi kerakligini unutmang. ResultUnionResolver klassini yaratib, __resolveType metodini aniqlaymiz.

TypeScript
1@Resolver('ResultUnion')
2export class ResultUnionResolver {
3  @ResolveField()
4  __resolveType(value) {
5    if (value.name) {
6      return 'Author';
7    }
8    if (value.title) {
9      return 'Book';
10    }
11    return null;
12  }
13}
Hint

Barcha dekoratorlar @nestjs/graphql paketidan eksport qilinadi.

Enumlar

Enumeration turlari muayyan ruxsat etilgan qiymatlar to'plami bilan cheklangan skalyarning maxsus turi (batafsil here). Bu sizga quyidagilarga imkon beradi:

  • bu turdagi har qanday argument ruxsat etilgan qiymatlardan biri ekanini tekshirish
  • type tizimi orqali maydon har doim yakunli qiymatlar to'plamidan biri bo'lishini ko'rsatish

Code first yondashuvi

Code first yondashuvida GraphQL enum turini aniqlash uchun shunchaki TypeScript enum yaratasiz.

TypeScript
1export enum AllowedColor {
2  RED,
3  GREEN,
4  BLUE,
5}

Shu bilan, @nestjs/graphql paketidan eksport qilinadigan registerEnumType funksiyasi yordamida AllowedColor enumini ro'yxatdan o'tkazing:

TypeScript
1registerEnumType(AllowedColor, {
2  name: 'AllowedColor',
3});

Endi turlaringizda AllowedColorni ko'rsatishingiz mumkin:

TypeScript
1@Field(type => AllowedColor)
2favoriteColor: AllowedColor;

Bu SDL formatida GraphQL sxemasining quyidagi qismini generatsiya qiladi:

Graphql
1enum AllowedColor {
2  RED
3  GREEN
4  BLUE
5}

Enum uchun tavsif berish uchun registerEnumType() funksiyasiga description propertysini uzating.

TypeScript
1registerEnumType(AllowedColor, {
2  name: 'AllowedColor',
3  description: 'The supported colors.',
4});

Enum qiymatlari uchun tavsif berish yoki qiymatni deprecated deb belgilash uchun valuesMap propertysini quyidagicha uzating:

TypeScript
1registerEnumType(AllowedColor, {
2  name: 'AllowedColor',
3  description: 'The supported colors.',
4  valuesMap: {
5    RED: {
6      description: 'The default color.',
7    },
8    BLUE: {
9      deprecationReason: 'Too blue.',
10    },
11  },
12});

Bu SDL formatida quyidagi GraphQL sxemasini generatsiya qiladi:

Graphql
1"""
2The supported colors.
3"""
4enum AllowedColor {
5  """
6  The default color.
7  """
8  RED
9  GREEN
10  BLUE @deprecated(reason: "Too blue.")
11}

Schema first yondashuvi

Schema first yondashuvida enumeratorni aniqlash uchun SDL bilan GraphQL enum yarating.

Graphql
1enum AllowedColor {
2  RED
3  GREEN
4  BLUE
5}

So'ng, mos TypeScript ta'riflarini yaratish uchun tiplashlarni generatsiya qilish funksiyasidan foydalanishingiz mumkin (bu quick start bobida ko'rsatilgan):

TypeScript
1export enum AllowedColor {
2  RED
3  GREEN
4  BLUE
5}

Ba'zan backend enumning qiymatini public API dagidan ichkarida boshqacha majburlashi mumkin. Bu misolda API RED ni o'z ichiga oladi, ammo resolverlarda buning o'rniga #f00 ishlatishimiz mumkin (batafsil here). Buni bajarish uchun AllowedColor enumi uchun resolver obyektini e'lon qiling:

TypeScript
1export const allowedColorResolver: Record<keyof typeof AllowedColor, any> = {
2  RED: '#f00',
3};
Hint

Barcha dekoratorlar @nestjs/graphql paketidan eksport qilinadi.

So'ng bu resolver obyektini GraphQLModule#forRoot() metodining resolvers propertysi bilan birga quyidagicha ishlating:

TypeScript
1GraphQLModule.forRoot({
2  resolvers: {
3    AllowedColor: allowedColorResolver,
4  },
5});