【问题标题】:How do you extend types in GraphQL?如何在 GraphQL 中扩展类型?
【发布时间】:2018-08-01 17:45:09
【问题描述】:

例如,Pet 是带有ownernameAnimal

type Animal {
  species: String
}

type Pet extends Animal {
  owner: Owner
  name: String
}

【问题讨论】:

标签: types graphql


【解决方案1】:

June2018 stable version of the GraphQL spec开始,一个Object类型可以扩展另一个Object类型:

对象类型扩展用于表示从某个原始类型扩展而来的类型。例如,这可能用于表示本地数据

在你的例子中,

type Animal {
  species: String
}

extend type Animal {
  owner: Owner
  name: String
}

这本身不是继承;您只能扩展基本类型,不能基于它创建新类型。请注意,新类型没有名称;现有的Animal 类型已扩展。

graphql.org documentation 没有提到任何关于extend 的内容,但文档是admittedly lackluster 并且是transitioned 来自Facebook 对Linux 基金会的所有权。 JavaScript 参考实现doesn't fully support extensions,但既然你已经标记了你的问题,你可以使用graphql-tools,其中does

const { graphql } = require('graphql');
const { makeExecutableSchema } = require('graphql-tools');

const typeDefs = `
  type Person {
    name: String!
  }
  extend type Person {
    salary: Int
  }  
  type Query {
    person: Person
  }
`;

const resolvers = {
  Query: {
    person: () => ({ name: "John Doe", salary: 1234 })
  }
}  

const schema = makeExecutableSchema({ typeDefs, resolvers });

graphql(schema, '{ person {name salary} }').then((response) => {
  console.log(response);
});

对于实际的类型继承,请参阅graphql-s2s library

【讨论】:

  • 所以,要明确一点,扩展一个类型就像将另一个值推入现有数组?就像你可以写const foo = [1, 2];,或者你可以写const foo = [1]; foo.push(2);...你可以写一个类型def,或者你可以写一个类型def并在以后扩展它?如果是这样,为什么有人会使用extend?将你的类型定义分成两个不同的地方有什么价值?
  • @machineghost:我同意这是一个残废/不成熟的实现。在this answer 中列出了使用它的一些原因。
  • 那么这样做有什么意义呢?我只考虑扩展导入或第 3 方模式的用例。
【解决方案2】:

虽然您不能创建子类/子类型,但您可以使用接口进行某种形式的继承:https://graphql.org/learn/schema/#interfaces

以上链接中的示例:

interface Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
}
type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  starships: [Starship]
  totalCredits: Int
}
 
type Droid implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  primaryFunction: String
}

查询时可以为不同的实现指定特定的字段

hero(episode: $ep) {
    name
    ... on Droid {
      primaryFunction
    }
    ... on Human {
      totalCredits
    }
  }

【讨论】:

    【解决方案3】:

    目前这在 GraphQL 中是不可能的,但是有一个实验包可能对此有用。

    https://github.com/Sydsvenskan/node-graphql-partials

    查看示例:

    partial LinkFields {
      links(
        rel: String
        type: String
      ): [Link]
    }
    
    partial DocumentFields using LinkFields {
      uuid: ID!
    
      # The document type, such as x-im/article
      type: String
      # If specified, then a list of the products to which this document's availability is limited
      products: [String]
      # The human readable name of the document, often used publicly to identify the document
      title: String
    
      # The specific path on the web page where this document is publicly available
      path: String
    
      # A single metadata block
      metaBlock(
        # The specific metadata block type to get
        type: String
      ): MetadataBlock
    }
    
    interface Document using DocumentFields {}
    
    type AuthorDocument implements Document using DocumentFields {}
    

    结果:

    type AuthorDocument implements Document {
      links(
        rel: String
        type: String
      ): [Link]
    
      uuid: ID!
    
      # The document type, such as x-im/article
      type: String
      # If specified, then a list of the products to which this document's availability is limited
      products: [String]
      # The human readable name of the document, often used publicly to identify the document
      title: String
    
      # The specific path on the web page where this document is publicly available
      path: String
    
      # A single metadata block
      metaBlock(
        # The specific metadata block type to get
        type: String
      ): MetadataBlock
    }
    

    由于这些只是字符串,您还可以创建一些辅助函数来修改字符串并插入必要的字段。

    如果你有兴趣关注 Github 上的讨论,可以看看下面的 issue。

    https://github.com/graphql/graphql-js/issues/703

    【讨论】:

    • 你可以使用extend type,这是可能的。
    【解决方案4】:

    其他答案是正确的,这不是专门化的类型扩展。

    请注意,类型扩展似乎有两种语法。根据Apollo Federation specification,graphql-java支持@extend语法。

    在 Apollo 文档中,语法似乎是:

    extend type Animal

    但根据联邦规范,也支持另一种语法:

    type Animal @key(fields: "id") @extends

    一些框架似乎只支持@ 语法。

    【讨论】:

      猜你喜欢
      • 2019-04-10
      • 2019-02-14
      • 2018-12-09
      • 2021-11-22
      • 2015-06-28
      • 1970-01-01
      • 2019-07-23
      • 2019-03-13
      • 2018-05-11
      相关资源
      最近更新 更多