如何实现 isTypeOf 方法?

How to implement isTypeOf method?

鉴于此架构:

interface INode {
  id: ID
}

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

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

鉴于此 class:

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
    }
  }
}

然后我得到下面的return:

{
  "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 函数,但我仍然收到错误消息。

我做错了什么?

备注:

isTypeOf 是一个函数,当您以编程方式创建模式时,它会传递给 GraphQLObjectType 的构造函数。 resolveType 函数和 unions/interfaces 同上。如果您使用 SDL 并使用 buildSchema 创建模式,则无法将这些函数注入到您创建的模式中,就像您无法为 [=16= 以外的类型的字段提供解析器一样] 和 Mutation.

你有几个选择。一种选择是利用默认的 resolveType 行为。这将检查对象上的 __typename 属性,然后回退到对每个实现类型调用 isTypeOf 直到它匹配。这意味着如果您使用的是 class,那么执行以下操作就足够了:

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

更好的选择是删除 buildSchema 并使用 graphql-tools 中的 makeExecutableSchema。然后,您可以直接在解析器中定义 resolveType and/or 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'
    },
  }
}

您不仅可以通过这种方式轻松定义 isTypeOfresolveType,还可以轻松地为任何类型的字段添加解析器并轻松添加自定义标量。如果您仅使用 buildSchema.

,则无法(轻松)执行任何操作

编辑:

如果您更喜欢使用 isTypeOf 而不是 resolveType,解析器将如下所示:

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

只有一个是必要的。为您使用的每个抽象类型编写一个 resolveType 函数, 为每个可能是抽象类型的对象类型编写一个 isTypeOf