Node.js 如何实现isTypeOf方法?
鉴于此模式:Node.js 如何实现isTypeOf方法?,node.js,typescript,express,graphql,express-graphql,Node.js,Typescript,Express,Graphql,Express Graphql,鉴于此模式: 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: a
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和expressgraphql李>
isTypeOf
是一个函数,当您以编程方式创建模式时,它会传递给GraphQLObjectType的构造函数。resolveType
函数和联合/接口也一样。如果您使用SDL并使用buildSchema
创建模式,则无法将这些函数注入到创建的模式中,就像您无法为除Query
和Mutation
之外的类型上的字段提供解析程序一样
你有两个选择。一个选项是利用默认的resolveType
行为。这将检查对象上的\uuu typename
属性,并返回到对每个实现类型调用isTypeOf
,直到它匹配为止。这意味着,如果您正在使用一个类,执行以下操作就足够了:
export default class Todo {
get __typename() {
return 'Todo'
}
}
const resolvers = {
Query: {
node: (obj, args, context, info) => {
return new Todo('1', 'Todo 1')
}
},
Todo: {
__isTypeOf: (obj, context, info) => {
return obj instanceof Todo
},
}
}
更好的选择是删除buildSchema
并使用graphql工具中的makeExecutableSchema
。然后可以直接在解析器中定义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
,则无法(轻松地)完成这些操作
编辑:
如果您喜欢使用isTypeOf
而不是resolveType
,则解析程序的外观如下所示:
export default class Todo {
get __typename() {
return 'Todo'
}
}
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
。Daniel,感谢您抽出时间。我尝试了第一个建议,但没有效果,所以现在我考虑继续你的第二个建议:使用makeExecutableSchema
。然而,我有一个担忧。我试图创建一个中继服务器,makeExecutableSchema
来自Apollo。到目前为止,我知道中继是一种“模式”,而阿波罗是一种具有不同实现的“框架”。所以我的问题是:在同一个解决方案中使用这两种方法不是不正确吗?如果您希望集成graphql-relay-js
,以制作符合中继的服务器,我相信,强制您使用vanilla GraphQL.js以编程方式生成模式——使用buildSchema
或makeExecutableSchema
从SDL构建模式可能不允许您合并中继库中包含的所有各种帮助器方法。否则,就有可能用graphql工具甚至apollo服务器构建一个中继兼容服务器?你看到了什么错误或行为?这里有一个使用Launchpad的工作示例,演示了我的建议:(Launchpad使用makeExecutableSchema,但概念仍然是一样的)“如果您希望集成graphql中继js以创建符合中继的服务器,我相信这会迫使您使用vanilla graphql.js以编程方式生成模式”-这正是我想要做的答案是否可以更新为包含isTypeOf实现?这是最初的问题,但它似乎并不能真正解释这一点。