我有一些类型本质上扩展了基本类型。我知道 GraphQL 并不完全支持这一点,所以我使用一个接口来定义基类,然后在基类型和扩展类型中实现它。它的好处是允许我使用共享片段。然而,我希望我可以在接口之外定义解析器,而不是在每个单独的类型中。有没有办法通过 GraphQL 本身定义共享解析器?
union Object = BaseObject | ObjectA | ObjectB
interface ObjectI {
id: ID!
relationalField: SomeOtherObject!
...
}
type BaseObject implements ObjectI {
id: ID!
relationalField: SomeOtherObject!
...
}
type ObjectA implements ObjectI {
id: ID!
relationalField: SomeOtherObject!
...
# more fields
uniqueA: String!
}
type ObjectB implements ObjectI {
id: ID!
relationalField: SomeOtherObject!
...
# more fields
uniqueB: String!
}
export const resolvers = {
Query: {
objects: async (parent, args, context, info) => dataSource.get(),
},
Object: {
__resolveType: (obj) => defineType(obj),
},
ObjectI: {
// this is what I am trying to do that doesn't work
relationalField: async (parent, args, context, info) => dataSource.getSomeOtherObject(parent),
},
// instead I have to define that resolver 3 times in each type
BaseObject: { },
ObjectA: { },
ObjectB: { },
}
我意识到我可以在其他地方创建一个在每个解析器中调用的函数变量。有用。但只是想知道是否有一种方法可以通过 GraphQL 层次结构来定义通用解析器?
:哎呀:
BaseObject: {
relationalField: async (parent, args, context, info) => dataSource.getSomeOtherObject(parent),
},
ObjectA: {
relationalField: async (parent, args, context, info) => dataSource.getSomeOtherObject(parent),
},
ObjectB: {
relationalField: async (parent, args, context, info) => dataSource.getSomeOtherObject(parent),
},
“解析器”不是 GraphQL 问题。它们甚至不在 GraphQL 规范中。这是一个特定于实施的问题。这个问题与 GraphQL 无关,除了你问题前面的层是 GraphQL。
查看您的代码,我假设您正在使用 Apollo Server,这使得这是一个 JavaScript(或 TypeScript)问题,因此您可以做任何您想做的事情。您可以使用一些GenericTypeResolver
类。你可以做一个解析器工厂。
interface GenericResolvers<T> {
loadById(id: string): T;
loadAll(): T[];
deleteById(id: string): T;
}
type EntityModel = typeof User | typeof Book | typeof Author;
const genericTypeResolverFactory = <T extends EntityModel>(model: T): GenericResolvers<T> => {
const dataSource = new DataSource<T>(model);
return {
loadById: (id: string) => dataSource.loadById(id),
loadAll: () => dataSource.loadAll(),
deleteById: (id: string) => dataSource.deleteById(id),
}
}
const resolvers = {
User: genericTypeResolverFactory(User),
Book: genericTypeResolverFactory(Book),
Author: genericTypeResolverFactory(Author),
}
甚至
const resolvers = [User, Book, Author].reduce((acc, model) => {
acc[model.constructor.name] = genericTypeResolverFactory(model);
return acc;
}, {} as Record<string, GenericResolvers<EntityModel>>);