我有以下代码片段:
export const NodeInterface = new GraphQLInterfaceType({
name: 'Node',
fields: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolveType: (source) => {
if (source.__tableName === tables.users.getName()) {
return UserType;
}
return PostType;
}
});
和使用该接口的
GraphQLObjectType
:export const PostType = new GraphQLObjectType({
name: 'Post',
interfaces: [ NodeInterface ],
fields: {
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: resolveId
},
createdAt: {
type: new GraphQLNonNull(GraphQLString),
},
body: {
type: new GraphQLNonNull(GraphQLString)
}
}
});
我必须定义什么接口?
最佳答案
在GraphQL中,接口实现两个目的:
它们确保实现它们的类型也实现特定的字段。例如,这里的Node
接口具有一个id
字段-这意味着实现Node
接口的任何类型都将需要具有id
字段(并且id
必须是ID标量就像接口中的标量一样。那些参数也是如此-接口字段中的任何参数也都必须存在于实现类型中的匹配字段上。
当一个字段需要两种或多种类型时,可以使用它们。一个字段将始终解析为一种类型或标量,但是,通过使用接口(或并集),我们在架构中指出该字段可以解析为一组类型之一。
假设我们在您的代码段中有一个Node
,实现了它的某些类型,以及一个返回Node的查询:
interface Node {
id: ID!
}
type Foo implements Node {
id: ID!
someFooField: String!
someOtherFooField: Int!
}
type Bar implements Node {
id: ID!
someBarField: String!
someOtherFooField: Int!
}
type Query {
getNode(id: ID!): Node!
}
在我们的示例中,
getNode
可以解析为Foo
或Bar
。当我们编写查询时,我们不知道将解决哪个查询。但是因为我们知道接口需要id
字段,所以我们可以编写如下查询:query OperationName {
getNode(id: "SOME_ID"){
id
}
}
但是,如果我们还需要查询
someBarField
,则无法执行此操作:query OperationName {
getNode(id: "SOME_ID"){
id
someBarField
}
}
因为
Foo
没有该字段。相反,我们必须利用一个片段,如下所示:query OperationName {
getNode(id: "SOME_ID"){
id
... on Bar {
someBarField
}
}
}
然后,将返回
someBarField
,但前提是该字段解析为类型Bar
。如果是Foo
,则仅返回ID。同样,您可以从实现相同接口的任何类型请求非共享字段:query OperationName {
getNode(id: "SOME_ID"){
id
... on Bar {
someBarField
}
... on Foo {
someFooField
}
}
}
最后但并非最不重要的一点是,工会的工作方式非常相似。但是,与接口不同,没有为联合定义任何共享字段,因此类型不会“实现”联合,而只是联合的一部分。这意味着在请求返回联合的字段时,由于没有共享字段可请求,因此您将始终必须使用片段。