Как добавить объединение типа в 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)
  }))
);

1 ответ

В GraphQL для добавления типа объединения в typedefs вы должны определить объединение

т.е. 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 Client

// 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 чтобы проверить, какой тип в ответе.

Примечание: для тех, кому интересно, почему я не использую ошибки GraphQL. Это потому, что Apollo плохо обрабатывает ошибки, когда сталкивается с ошибкой graphQL. Так что для работы я пытаюсь вернуть обычай ApiError в моем ответе.

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