如何在 GraphQL 中继承或扩展 typeDef
Posted
技术标签:
【中文标题】如何在 GraphQL 中继承或扩展 typeDef【英文标题】:How to Inherit or Extend typeDefs in GraphQL 【发布时间】:2018-05-11 10:14:26 【问题描述】:我有一个type User
。用户也可以是type TeamMember
。 User
和 TeamMember
之间的唯一区别是添加了字段 teamRole: String
。所以,我很想做类似下面的事情,以避免重复定义所有用户的字段……
type User
id: ID!,
name: String,
(many other field defs)
type TeamMember extends User
teamRole: String,
有人知道这个的语法吗?我以为extend
会是答案,但它看起来更像是javascript 的prototype
【问题讨论】:
【参考方案1】:使用像 graphql-s2s 这样的模式转译器来实现继承可能是大材小用,而且 graphql-s2s 到 2021 年就已经过时了。
看看这个 Apollo Server 指令:https://github.com/jeanbmar/graphql-inherits
const typeDefs = gql`
directive @inherits(type: String!) on OBJECT
type Car
manufacturer: String
color: String
type Tesla @inherits(type: "Car")
manufacturer: String
papa: String
model: String
`;
class InheritsDirective extends SchemaDirectiveVisitor
visitObject(type)
const fields = type.getFields();
const baseType = this.schema.getTypeMap()[this.args.type];
Object.entries(baseType.getFields()).forEach(([name, field]) =>
if (fields[name] === undefined)
fields[name] = field;
);
【讨论】:
【参考方案2】:extend
关键字非常适合如果您有一个基本架构并希望基于它构建两个或多个可用架构。例如,您可以使用所有模式共享的查询定义一个根 Query
类型,然后在每个单独的模式中扩展它以添加特定于该模式的查询。它还可以用于模块化模式。但是,它只是一种向现有类型添加功能的机制——它不能用于创建新类型。
GraphQL 本身并不支持继承。没有任何语法可以帮助您避免跨多种类型的字段重复。
您可以利用字符串插值来避免一次又一次地输入相同的字段:
const sharedFields = `
foo: String
bar: String
`
const typeDefs = `
type A
$sharedFields
type B
$sharedFields
`
除此之外,您还可以使用像 graphql-s2s 这样的库,它允许您利用继承和泛型类型。不过,以这种方式生成的模式仍然必须编译为有效的 SDL —— 充其量,像 graphql-s2s
这样的库只是提供一些语法糖和更好的 DX。
最后,您可以重新构建类型以避免字段重复,但代价是更结构化的响应。例如,不要这样做:
type A
a: Int
foo: String
bar: String
type B
b: Int
foo: String
bar: String
你可以这样做:
type X
foo: String
bar: String
aOrB: AOrB
union AOrB = A | B
type A
a: Int
type B
b: Int
【讨论】:
谢谢!这正是我一直在寻找的。嗯,不完全是,因为理想情况下我不需要另一个包,但graphql-s2s
给了我我需要的东西。我使用graphql-yoga
作为我的服务器,所以我不得不monkey patch their typeDefs
声明,这也不太理想。如果您知道更好的方法,我会全力以赴。谢谢!
到 2019 年年中,这是否仍然不可用?
@A.com 是的。可以看到最新的规范here。
@Alexander 这不是标准指令——它使用的是什么库?
当我使用谷歌搜索确切的短语“@inherit from”时,这个堆栈溢出问题是唯一出现的页面。你发明了一个全新的句子。以上是关于如何在 GraphQL 中继承或扩展 typeDef的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 Typescript 的泛型将中继(graphql)连接映射到边缘节点