如何实现isTypeOf方法?

Sau*_*ulo 2 node.js express typescript graphql express-graphql

给定此架构:

interface INode {
  id: ID
}

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

type Query {
  node(id: ID!): INode
}
Run Code Online (Sandbox Code Playgroud)

给定此类:

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

  isTypeOf(value: any): Boolean {
    return value instanceof Todo;
  }
}
Run Code Online (Sandbox Code Playgroud)

使用此解析器:

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

当我调用查询时:

query {
  node(id: "1") {
    id
    ... on Todo {
      title
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我得到下面的回报:

{
  "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
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我已经实现了该isTypeOf功能,但仍收到错误消息。

我究竟做错了什么?

笔记:

  • 我正在使用Typescript,express和express-graphql;

Dan*_*den 5

isTypeOf是一个函数,当您以编程方式创建架构时,该函数将传递给GraphQLObjectType的构造函数。resolveType功能和联合/接口的同上。如果您使用SDL并使用创建您的架构buildSchema,则无法将这些函数注入到您创建的架构中,就像您无法为Queryand 以外的类型的字段提供解析器一样Mutation

您有两种选择。一种选择是利用默认resolveType行为。这将检查__typename对象的属性,并回退到isTypeOf对每种实现类型进行调用,直到匹配为止。这意味着,如果您使用的是类,则要做这样的事情就足够了:

export default class Todo {
  get __typename() {
    return 'Todo'
  }
}
Run Code Online (Sandbox Code Playgroud)

更好的选择是放弃buildSchema,并使用makeExecutableSchemagraphql-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'
    },
  }
}
Run Code Online (Sandbox Code Playgroud)

您不仅可以轻松地定义isTypeOf或以resolveType这种方式,还可以轻松地为任何类型的字段添加解析器,并轻松添加自定义标量。如果您只使用just,那么您将无法(轻松地)执行任何操作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
    },
  }
}
Run Code Online (Sandbox Code Playgroud)

只需一个或另一个。无论是写一个resolveType函数为您使用的每个抽象类型,isTypeOf为这可能是一个抽象类中的每个对象类型。

  • 可以更新答案以包含 isTypeOf 实现吗?这是最初的问题,但实际上似乎并没有这样解释。 (2认同)