Как реализовать метод isTypeOf? - PullRequest
0 голосов
/ 31 октября 2018

С учетом этой схемы:

interface INode {
  id: ID
}

type Todo implements INode {
  id: ID
  title: String!
}

type Query {
  node(id: ID!): INode
}

Учитывая этот класс:

export default class Todo {
  constructor (public id: string, public title: string) { }

  isTypeOf(value: any): Boolean {
    return value instanceof Todo;
  }
}

С учетом этого резольвера:

type NodeArgs = {
  id: string
}
export const resolver = {
  node: ({ id }: NodeArgs) => {
    return new Todo('1', 'Todo 1');
  }
}

Когда я вызываю запрос:

query {
  node(id: "1") {
    id
    ... on Todo {
      title
    }
  }
}

Тогда я получаю возврат ниже:

{
  "errors": [
    {
      "message": "Abstract type INode must resolve to an Object type at runtime for field Query.node with value { id: \"1\", title: \"Todo 1\" }, received \"undefined\". Either the INode type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "node"
      ]
    }
  ],
  "data": {
    "node": null
  }
}

Как видите, я реализовал функцию isTypeOf, но я все еще получаю сообщение об ошибке.

Что я делаю не так?

Примечания:

  • Я использую Typescript, express и express-graphql;

1 Ответ

0 голосов
/ 31 октября 2018

isTypeOf - это функция, которая передается в конструктор GraphQLObjectType при программном создании схемы. То же самое для resolveType функций и союзов / интерфейсов. Если вы используете SDL и создаете свою схему, используя buildSchema, невозможно внедрить эти функции в созданную вами схему, так же как у вас нет способа предоставить средства распознавания для полей типов, отличных от Query и * 1005. *.

У вас есть несколько вариантов. Один из вариантов - использовать поведение по умолчанию resolveType. Это проверяет свойство __typename объекта и возвращается к вызову isTypeOf для каждого реализующего типа, пока он не совпадет. Это означает, что если вы используете класс, этого должно быть достаточно, например:

export default class Todo {
  get __typename() {
    return 'Todo'
  }
}

Лучшим вариантом будет сбросить buildSchema и использовать makeExecutableSchema с graphql-tools. Затем вы можете определить свои функции resolveType и / или isTypeOf непосредственно в ваших резольверах. Например:

const resolvers = {
  Query: {
    node: (obj, args, context, info) => {
      return new Todo('1', 'Todo 1')
    }
  },
  INode: {
    __resolveType: (obj, context, info) => {
      if (obj instanceof Todo) return 'Todo'
    },
  }
}

Вы можете не только легко определить isTypeOf или resolveType, вы также можете легко добавить средства распознавания для полей любого типа и добавлять собственные скаляры без каких-либо хлопот. Вы не можете сделать это (легко), если вы используете просто buildSchema.

...