【问题标题】:How to Inherit or Extend typeDefs in GraphQL如何在 GraphQL 中继承或扩展 typeDef
【发布时间】: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 会是答案,但它看起来更像是javascript 的prototype

【问题讨论】:

    标签: inheritance schema graphql extend extends


    【解决方案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”时,这个堆栈溢出问题是唯一出现的页面。你发明了一个全新的句子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 2017-05-18
      • 2014-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多