如何在 GraphQL 中继承或扩展 typeDef

Posted

技术标签:

【中文标题】如何在 GraphQL 中继承或扩展 typeDef【英文标题】:How to Inherit or Extend typeDefs in GraphQL 【发布时间】:2018-05-11 10:14:26 【问题描述】:

我有一个type User。用户也可以是type TeamMemberUserTeamMember 之间的唯一区别是添加了字段 teamRole: String。所以,我很想做类似下面的事情,以避免重复定义所有用户的字段……

  type User 
    id: ID!,
    name: String,
    (many other field defs)
  

  type TeamMember extends User  
    teamRole: String,
  

有人知道这个的语法吗?我以为extend 会是答案,但它看起来更像是javascriptprototype

【问题讨论】:

【参考方案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的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL,中继:处理错误

如何使用带有 Typescript 的泛型将中继(graphql)连接映射到边缘节点

无论如何要检查中继是不是注入了graphql服务器?

如何在现有 GraphQL 服务器上添加根和查看器查询以支持中继

GraphQL 和中继过滤 UI

如何使用中继将自定义标头发送到graphql服务器?