从10月8日至10日加入我们,在纽约市了解GraphQL联邦和API平台工程的最新的技巧、趋势和新闻。加入我们参加在纽约市举行的GraphQL Summit 2024
文档
免费开始

类型条件


关于 包含接口和联合作为抽象类型, 可遵守。一个带有抽象返回类型的 可返回任何可转换为抽象类型的具体类型。type 可转换为抽象类型。

考虑以下架构

StarWarsSchema.graphql
type Query {
hero: Character!
}
interface Character {
name: String!
}
type Human implements Character {
name: String!
}
type Droid implements Character {
name: String!
primaryFunction: String!
}

由于HumanDroid类型都实现了Character接口,因此它们都可以转换为抽象类型Character。这意味着Character类型的字段(例如,hero),可以是HumanDroid。当我们hero字段时,服务器不会返回Character类型的响应对象,而是返回实现了Character接口的具体类型。在这种情况下,它可以是HumanDroid

类型转换

为了知道响应中对象的类型是否可以转换为另一个类型,我们必须知道对象的实际类型。我们可以请服务器提供对象的实际类型通过获取__typename元数据字段。

Apollo iOS自动扩展您的查询,将__typename字段添加到您操作中的每一个对象。这主要是为了支持条件类型转换,但也意味着__typename属性始终定义,并在需要时可以用来手动区分对象类型。

根据以下规则,可以基于以下规则将对象转换为另一种类型,其中“目标类型”是我们试图转换为的类型:

  • 如果目标类型是一个具体的对象类型
    • 如果对象类型与目标类型完全相同。
  • 如果目标类型是接口
    • 如果对象类型实现了目标接口类型。
  • 如果目标类型是联合体
    • 如果目标联合体类型的可能集合包括对象类型。

使用类型条件进行查询

任何时候我们想要查询类型特定的字段在具有抽象类型的对象上,我们必须使用类型条件。

在这个示例中,我们想要查询 hero 字段上的 primaryFunction,但是只有当返回的 heroDroid 类型时,我们才能查询 primaryFunction 字段。下面的查询定义是无效的且无法编译:

HeroAsDroidQuery.graphql
query HeroAsDroid {
hero {
name
primaryFunction # Field "primaryFunction" does not exist on type "Character"
}
}

我们可以使用在 Droid 类型上的 来查询 primaryFunction 字段。这可以是 命名片段内联片段

内联片段
query HeroAsDroid {
hero {
name
... on Droid {
primaryFunction
}
}
}
命名片段
query HeroAsDroid {
hero {
name
...DroidDetails
}
}
fragment DroidDetails on Droid {
name
primaryFunction
}

访问条件响应数据

使用另一个类型的片段会在生成的模型对象中创建一个类型条件。

为了访问 Hero 模型中的 primaryFunction,我们需要知道英雄是否是机器人。Apollo iOS 将生成一个包含可选项 asDroid 属性的 Hero 模型:

HeroAsDroidQuery.graphql.swift
class HeroAsDroidQuery: GraphQLQuery {
struct Data: SelectionSet {
let hero: Hero
struct Hero: SelectionSet {
let name: String
var asDroid: AsDroid? { ... }
// Type Condition Declaration
struct AsDroid: InlineFragment {
let name: String
let primaryFunction: String
}
}
}
}

属性 hero.asDroid 是可选的,并且只有在响应数据的英雄对象类型为机器人时才会返回值。现在我们可以有条件地将 Hero 转换为 AsDroid 模型并访问 primaryFunction 属性。

let primaryFunction: String? = hero.asDroid?.primaryFunction

转换为条件命名片段

如果类型条件是由命名片段创建的,asDroid 对象也可以用来执行 片段转换

在这里,我们使用一个名为 DroidDetails 的片段声明类型条件:

查询 & 片段定义
query HeroAsDroid {
hero {
name
...DroidDetails
}
}
fragment DroidDetails on Droid {
name
primaryFunction
}
生成的模型
class HeroAsDroidQuery: GraphQLQuery {
struct Data: SelectionSet {
let hero: Hero
struct Hero: SelectionSet {
let name: String
var asDroid: AsDroid? { ... }
// Type Condition Declaration
struct AsDroid: InlineFragment {
let name: String
let primaryFunction: String
// Fragment Conversion Declaration
var fragments: Fragments
struct Fragments {
var droidDetails: DroidDetails { ... }
}
}
}
}
}

为了将 Hero 转换为 DroidDetails 片段,我们需要知道英雄是否是机器人。使用命名片段,Apollo iOS 生成一个包含转换为 DroidDetailsHero.AsDroid 模型。现在我们可以将可选项转换为 DroidDetails 片段。

let droidDetails: DroidDetails? = hero.asDroid?.fragments.droidDetails

了解更多关于如何使用命名 以在我们的 片段 文档

上一页
错误处理
下一页
自定义标量类型
评价文章评价在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,商号为 Apollo GraphQL。

隐私政策

公司