Как добавить тип объединения в Apollo graphql

Я создал этот вопрос на случай, если кому-то будет интересно, как добавить союз / полиморфные типы в Apollo. Надеюсь, это облегчит им задачу.

В этом примере я хотел, чтобы ответ был либо Worksheet, либо ApiError.

// typedefs.js
export default [`
  schema {
    query: Query
  }

  type Query {
    worksheet(id: String!): Worksheet | Error
  }

  type Worksheet {
    id: String!
    name String
  }

  type ApiError {
    code: String!
    message: String!
  }
`];

// resolvers.js
export default {
  Query: {
    worksheet(_, args, { loaders }) {
      return loaders.worksheet.get(args.id).catch(() => {
        // ApiError
        return {
          code: '1',
          message: 'test'
        }
      });
    }
  }
};

// Express Server 
import { graphqlExpress } from 'apollo-server-express';
import { makeExecutableSchema } from 'graphql-tools';
import typeDefs from './typedefs';
import resolvers from './resolvers';

...


app.post(
  '/graphql',
  graphqlExpress(req => ({
    makeExecutableSchema({ typeDefs, resolvers }),
    context: mkRequestContext(req.ctx, req.log),
    formatError: formatGraphQLError(req.ctx, req.log)
  }))
);
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
3 326
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В GraphQL, чтобы добавить тип объединения в определения типов, вы должны определить союз

т.е. union WorksheetOrError = Worksheet | ApiError

// typedefs.js
export default [
  `
  schema {
    query: Query
  }

  type Query {
    worksheet(id: String!): WorksheetOrError
  }

  union WorksheetOrError = Worksheet | ApiError 

  type Worksheet {
    id: String!
    name String
  }

  type ApiError {
    code: String!
    message: String!
  }
`];

В преобразователях вы должны определить преобразователь для типа объединения, который имеет свойство __resolveType. Это поможет сообщить исполнителю GraphQL, к какому типу относится результат.

 // resolvers.js
export default {
  Query: {
    worksheet() {
      ... 
    }
  },
  WorksheetOrError: {
    __resolveType(obj) {
      if (obj.id) {
        return 'Worksheet';
      }

      if (obj.code) {
        return 'ApiError';
      }

      return null;
    }
  },
};

Чтобы создать запрос GraphQL в Клиент Apollo

// Your application code. 

// This is my Worksheet Query in my React code.
const WorksheetQuery = gql`
  query GetWorksheet($worksheetId: String!) {
    worksheet(id: $worksheetId) {
      ... on Worksheet {
        id
        name
      }
      ... on ApiError {
        code
        message
      }
    }
  }

Теперь вы можете проверить __typename, чтобы проверить, какой тип в ответе.

Note: For those who are wondering why I'm not using GraphQL errors. It's because Apollo doesn't seem to handle errors well when it encounters a graphQL error. So for a work around I'm trying to return a custom ApiError in my response.

Есть несколько причин, по которым использование объединения с типом ошибки - это хорошо.

  1. В настоящее время, если вам нужен частичный ответ с помощью GraphQLError. Apollo не кэширует ошибки, поэтому, если вы захотите повторно использовать кешированный ответ позже, у вас не будет полного ответа, так как ошибки будут удалены. (Теперь вы не можете отображать правильный интерфейс с ошибками)
  2. Получение GraphQLError обратно в Apollo вернет плоский список ошибок с путем к тому, где ошибка находится в данных. Таким образом, вам нужно будет проверить, в какой части вашей схемы возникла ошибка. Однако, если вы будете следовать приведенным выше инструкциям, у вас уже будет ошибка в схеме. Таким образом, вы уже знаете, в какой части схемы произошла ошибка.

Другие вопросы по теме