什么是联合类型
联合类型(Union Type)在 GraphQL 中是一种非常重要的数据类型。它允许我们定义一个字段可以返回多种不同的类型,这些类型可能是完全不同的,但是它们都具有相同的字段或特征,而且它们之间是相互竞争或互斥的。
例如:假设我们要定义一个 search
查询,它需要返回 User
和 Movie
两种类型,但是这两种类型分别属于不同的数据集合。在这种情况下,我们可以利用联合类型来解决问题。定义如下:
-- -------------------- ---- ------- ----- ------------ - ---- - ----- ---- ----- - ------------- --------- ---------------- - ---- ---- - --- --- ----- ------- - ---- ----- - --- --- ------ ------- -
在上面的查询定义中,SearchResult
联合类型可以包含 User
或 Movie
两种类型,search
查询可以返回一个 SearchResult
数组。当客户端请求查询时,服务器根据查询的参数以及条件,决定要返回的结果是 User
还是 Movie
。
明白了联合类型的基本概念和用途之后,我们接下来可以看看在实际开发中如何使用这种类型。
在实际开发中如何使用联合类型
声明
在声明联合类型时,只需要通过 union
关键字,列举出所包含类型即可。
union SearchResult = User | Movie
需要注意的是:联合类型只能包含对象类型,即类型 User
和 Movie
必须是 GraphQL 中的对象类型,不能是标量类型。
使用
联合类型的使用非常灵活,可以用于定义返回类型、变量类型、参数类型等等。以下是一些基本的使用方法。
查询
查询是 GraphQL 中最常用的操作之一,使用联合类型可以更方便地处理多种类型的查询结果。
type Query { search(query: String!): [SearchResult!]! }
在上面的查询定义中,参数 query
是查询参数,返回值是 [SearchResult!]!
类型的数组,这个数组包含多种类型的结果。
变量
在 GraphQL 中,联合类型也可以用于定义变量类型,这样变量就可以接受多种类型的输入。
-- -------------------- ---- ------- ----- ----------------- - --- --- ----- ----------------- - ---- ---------------- - ---- ----- - ---- -------- - -------------------------- -------------------- ------------- -
在上面的示例中,SearchResultInput
是一个输入类型,包含 id
和 type
两个字段,其中 type
的类型是枚举类型 SearchResultType
,这个枚举类型包含了 USER
和 MOVIE
两个值,用于区分联合类型的不同类型。updateSearchResult
是一个更新类型,参数 result
的类型是 SearchResultInput
,返回类型是 SearchResult
。
联合类型在查询结果中的定义
在 GraphQL 中,查询结果必须声明出所有可能的返回值类型,以便客户端进行类型推断。在联合类型中,我们可以使用关键词 ...on
来列举出联合类型中包含的所有类型。
假设我们要实现一个简单的搜索引擎,查询结果为 User
或 Movie
,并且在前端中需要根据不同的类型分别显示不同的信息。在这种情况下,我们可以使用 ...on
定义不同的类型。
-- -------------------- ---- ------- ----- -------------- -------- - ------------- ------- - --- -- ---- - -- ---- - --- -- ----- - -- ----- - - -
在上面的查询中,$query 是查询参数,查询 search
返回的结果包含多种类型,使用 ... on
列举出不同类型的字段。当客户端请求时,服务器根据查询参数,决定返回的结果是 User
还是 Movie
。
手动处理联合类型
虽然 ... on
可以帮我们自动处理联合类型,但是有时候我们需要手动操作联合类型,这时候就需要了解 GraphQL 中的一些内置函数。以下是一些常用的内置函数。
__typename
:返回当前对象的类型名称,用于区分联合类型的不同类型。__typename
和... on
结合使用,用于手动处理联合类型。
例如:
-- -------------------- ---- ------- - ------------- -------- - ---------- --- -- ---- - -- ---- - --- -- ----- - -- ----- - - -
在上面的查询中,我们手动添加了 __typename
对象,并将 User
和 Movie
两种类型分开进行处理。
联合类型的最佳实践
在实际开发中,为了使联合类型更加灵活和易用,我们需要遵循一些最佳实践。
统一命名规范
联合类型可能包含多种不同的类型,其中每种类型都可能有自己的属性和方法。为了方便客户端进行开发和维护,我们需要对不同类型的属性和方法进行统一的命名规范。
例如:假设我们要定义一个联合类型 SearchResult
,其中包含多种类型:User
和 Movie
。为了方便客户端直接使用类型的属性和方法,我们需要为每个类型编写特定的方法,用于统一属性和方法的名称。
-- -------------------- ---- ------- ----- ------------ - ---- - ----- ---- ----- - ------------- --------- ---------------- - ---- ---- - --- --- ----- ------- - ---- ----- - --- --- ------ ------- - --------- --------------------- - --- --- ----- ------- ------ ------- - ---- ---------------- ---------- --------------------- - --- --- ----- ------- ------ ------- ----------- ------- - ---- ----------------- ---------- --------------------- - --- --- ----- ------- ------ ------- ----------- ------- - ---- -------------------- - ----------- ------- ----- ---------------------- - ---- ----- - ------------- --------- ------------------------ -
在上面的示例中,我们为每个类型定义了一个 SearchResultInterface
接口,这个接口包含三个字段:id
、name
和 title
。SearchResultUser
和 SearchResultMovie
是 SearchResult
联合类型中的具体类型,分别用于表示 User
和 Movie
两种类型。
最后,我们还定义了一个 SearchResultListItem
类型,它包含一个 __typename
字段和一个 data
字段,用于向客户端返回数据。
对数据集合进行分类
在设计联合类型时,我们应该遵循 聚合(composition)
模式,即将不同类型的数据集合进行分类。具体来说,将不同类型的数据集合放在不同的 GraphQL 对象中,然后再定义一个联合类型来引用这些对象。
例如:假设我们有两个数据集合:User
和 Movie
。这两个数据集合虽然拥有相同的字段,但是它们是完全不同的对象,用于不同的场景。在这种情况下,我们应该将它们放在不同的对象中,然后再定义一个联合类型 SearchResult
引用这些对象。
-- -------------------- ---- ------- ---- ----- - ----------------- --------- -------- ------------------ --------- --------- - ---- ---- - --- --- ----- ------- - ---- ----- - --- --- ------ ------- - ----- ------------ - ---- - ----- ---- ----- - ------------- --------- ---------------- -
在上面的示例中,我们将 User
和 Movie
放在不同的对象中,然后再定义了一个联合类型 SearchResult
,用于表示这两种类型之间的相似性。
避免类型耦合
为了避免类型耦合,我们需要将联合类型和接口进行分离,避免将联合类型和某个具体接口耦合在一起。这样可以增加代码的维护性,并更容易添加新的类型。
例如:假设我们有两个数据集合:User
和 Movie
,它们都有各自的属性和方法。为了避免将联合类型和某个具体接口耦合在一起,我们需要将 User
和 Movie
分别放在不同的对象中,然后再定义两个接口 UserInterface
和 MovieInterface
,用于定义属性和方法。最后定义一个联合类型 SearchResult
引用这两个接口。
-- -------------------- ---- ------- --------- ------------- - --- --- ----- ------- ------ ------ - --------- -------------- - --- --- ------ ------- ------ ------ - ---- ---- ---------- ------------- - --- --- ----- ------- ------ ------ - ---- ----- ---------- -------------- - --- --- ------ ------- ------ ------ - ----- ------------ - ------------- - -------------- ---- ----- - ------------- --------- ---------------- -
在上面的示例中,我们将 User
和 Movie
分别放在不同的对象中,然后定义了两个接口 UserInterface
和 MovieInterface
,用于定义属性和方法。最后定义一个联合类型 SearchResult
引用这两个接口。
结论
联合类型是 GraphQL 中非常重要的一种数据类型,它可以让我们更加灵活地处理具有多样性的数据集合。要善于运用联合类型,我们需要了解联合类型的基本知识和使用技巧,同时还需要遵循一些最佳实践,例如统一命名规范、对数据集合进行分类、避免类型耦合等。只有这样,我们才能更加灵活地使用 GraphQL 接口,更好地提供服务。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/671da2649babaf620fb7501c