[英]Graphql resolveType union: throwing must resolve to an object type at runtime
[英]GraphQL.js - use Interface as a default (fallback) type in resolveType function
如果提供的类型都不匹配,我试图在resolveType
函数中返回泛型。 下面的示例显示了此问题:API就像支持UserType
和MovieType
一样工作,直到在数据库中添加BookType
(GraphQL模式不支持)。
const {
graphql,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLNonNull,
GraphQLList,
GraphQLInterfaceType
} = require("graphql");
const DATA = [
{
// UserType
name: "catherine woolf",
nick: "catherine"
},
{
// MovieType
name: "cat woman",
director: "Jack Wolfgang"
},
{
// --- missing type --- (BookType)
name: "cats secrets",
author: "Nicky Glace"
}
];
const resolveType = data => {
if (data.nick) {
return UserType;
}
if (data.director) {
return MovieType;
}
};
const SearchableType = new GraphQLInterfaceType({
name: "Searchable",
fields: {
name: { type: GraphQLString }
},
resolveType: resolveType
});
const UserType = new GraphQLObjectType({
name: "User",
interfaces: [SearchableType],
fields: {
name: { type: GraphQLString },
nick: { type: GraphQLString }
}
});
const MovieType = new GraphQLObjectType({
name: "Movie",
interfaces: [SearchableType],
fields: {
name: { type: GraphQLString },
director: { type: GraphQLString }
}
});
const schema = new GraphQLSchema({
types: [MovieType, UserType, SearchableType],
query: new GraphQLObjectType({
name: "RootQueryType",
fields: {
search: {
type: new GraphQLList(SearchableType),
args: {
text: { type: new GraphQLNonNull(GraphQLString) }
},
resolve(_, { text }) {
return DATA.filter(d => d.name.indexOf(text) !== -1);
}
}
}
})
});
const query = `
{
search(text: "cat") {
name
... on User {
nick
}
... on Movie {
director
}
}
}
`;
graphql(schema, query).then(result => {
console.log(JSON.stringify(result, null, 2));
});
所以现在这段代码以错误结尾:
“抽象类型Searchable必须在运行时解析为值为RootQueryType.search的对象类型,其值为\\“ [object Object] \\”,接收为\\“ undefined \\”。Searchable类型应提供一个\\“ resolveType \\”函数,或者每个可能的类型应提供\\“ isTypeOf \\”函数。
这不足为奇,因为当前resolveType
可能不返回任何类型。
板条箱类型包含相同的字段,例如接口SearchableType
(1对1的实现):
const _SearchableType = new GraphQLObjectType({
name: '_Searchable',
interfaces: [SearchableType],
fields: {
name: { type: GraphQLString },
}
});
使用它作为后备类型:
const resolveType = data => {
if (data.nick) {
return UserType;
}
if (data.director) {
return MovieType;
}
return _SearchableType;
};
并将其添加到schema
定义中的types
:
types: [MovieType, UserType, SearchableType, _SearchableType],
但是此解决方案的问题是这样的伪_SearchableType
在如下文档中的存在:
有什么方法可以返回接口SearchableType
或resolveType
等效接口吗? 对我而言,关键点是在文档中隐藏了这种“后备类型”。
GraphQL是强类型的,在解决联合和接口时不支持泛型或某种“后备”机制。 归根结底,如果您的基础数据层返回的是您尚未在架构中实现的某种类型,那么最简单的解决方案是将该类型添加到架构中。 迁移到数据库和更改架构应该同时进行。
如果要从存储层派生架构,建议您使用PostGraphile (以前称为PostGraphQL)之类的工具。
就是说,如果您打算使用一种解决方法,则可以使用现有类型之一:
const resolveType = data => {
if (data.nick) {
return UserType
}
return MovieType
}
现在,只要您在界面(而不是其中一种类型)上进行查询,一本书的名称仍然可以访问。 这种方法的唯一缺点是,将为书籍返回特定于电影的字段,并将其解析为null,但这不会引起任何问题,除非在您的模式中将它们明确定义为非null。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.