GraphQL.js - 在 resolveType 函数中使用接口作为默认(后备)类型
Posted
技术标签:
【中文标题】GraphQL.js - 在 resolveType 函数中使用接口作为默认(后备)类型【英文标题】:GraphQL.js - use Interface as a default (fallback) type in resolveType function 【发布时间】:2018-09-23 04:21:57 【问题描述】:如果没有提供的类型匹配,我将尝试在 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 Object]\",收到 \"undefined\"。Searchable 类型应提供 \"resolveType\"函数或每种可能的类型都应该提供一个“isTypeOf”函数。”
这并不奇怪,因为目前 resolveType
可能不会返回任何类型。
解决方法
包含与接口 SearchableType
相同字段的 Crate 类型(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;
;
并将其添加到types
定义中的schema
:
types: [MovieType, UserType, SearchableType, _SearchableType],
但是这个解决方案的问题是在这样的文档中存在这个虚拟的_SearchableType
:
问题
有没有办法返回接口SearchableType
或resolveType
中的等效接口?对我来说,关键是在文档中隐藏这种“后备类型”。
【问题讨论】:
【参考方案1】:GraphQL 是强类型的,在解析联合和接口时不支持泛型或某种“回退”机制。归根结底,如果您的底层数据层正在返回您尚未在架构中实现的某种类型,那么最简单的解决方案就是将该类型添加到您的架构中。迁移到数据库和更改架构应该齐头并进。
如果您想从存储层派生架构,我建议您查看 PostGraphile(以前称为 PostGraphQL)之类的内容。
也就是说,如果您一心想要使用解决方法,您可以回退到现有类型之一:
const resolveType = data =>
if (data.nick)
return UserType
return MovieType
现在仍然可以访问一本书的名称,前提是您在界面上查询它而不是其中一种类型。这种方法的唯一缺点是电影特定的字段将返回一本书并解析为 null,但这不会导致任何问题,除非它们在您的架构中明确定义为非 null。
【讨论】:
以上是关于GraphQL.js - 在 resolveType 函数中使用接口作为默认(后备)类型的主要内容,如果未能解决你的问题,请参考以下文章
如何在express中实现resolveType函数/初始化graphQL服务器
Graphql + Relay graphql-relay-js 依赖
GraphQL JS 使用 .graphql 文件从节点 js 进行查询