如何实现 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
函数,但我仍然收到错误消息。
我做错了什么?
备注:
- 我正在使用 Typescript、express 和 express-graphql;
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'
},
}
}
您不仅可以通过这种方式轻松定义 isTypeOf
或 resolveType
,还可以轻松地为任何类型的字段添加解析器并轻松添加自定义标量。如果您仅使用 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
。
鉴于此架构:
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
函数,但我仍然收到错误消息。
我做错了什么?
备注:
- 我正在使用 Typescript、express 和 express-graphql;
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'
},
}
}
您不仅可以通过这种方式轻松定义 isTypeOf
或 resolveType
,还可以轻松地为任何类型的字段添加解析器并轻松添加自定义标量。如果您仅使用 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
。