在 GraphQL 中使用联合类型的最佳实践

阅读时长 9 分钟读完

什么是联合类型

联合类型(Union Type)在 GraphQL 中是一种非常重要的数据类型。它允许我们定义一个字段可以返回多种不同的类型,这些类型可能是完全不同的,但是它们都具有相同的字段或特征,而且它们之间是相互竞争或互斥的。

例如:假设我们要定义一个 search 查询,它需要返回 UserMovie 两种类型,但是这两种类型分别属于不同的数据集合。在这种情况下,我们可以利用联合类型来解决问题。定义如下:

-- -------------------- ---- -------
----- ------------ - ---- - -----

---- ----- -
  ------------- --------- ----------------
-

---- ---- -
  --- ---
  ----- -------
-

---- ----- -
  --- ---
  ------ -------
-

在上面的查询定义中,SearchResult 联合类型可以包含 UserMovie 两种类型,search 查询可以返回一个 SearchResult 数组。当客户端请求查询时,服务器根据查询的参数以及条件,决定要返回的结果是 User 还是 Movie

明白了联合类型的基本概念和用途之后,我们接下来可以看看在实际开发中如何使用这种类型。

在实际开发中如何使用联合类型

声明

在声明联合类型时,只需要通过 union 关键字,列举出所包含类型即可。

需要注意的是:联合类型只能包含对象类型,即类型 UserMovie 必须是 GraphQL 中的对象类型,不能是标量类型。

使用

联合类型的使用非常灵活,可以用于定义返回类型、变量类型、参数类型等等。以下是一些基本的使用方法。

查询

查询是 GraphQL 中最常用的操作之一,使用联合类型可以更方便地处理多种类型的查询结果。

在上面的查询定义中,参数 query 是查询参数,返回值是 [SearchResult!]! 类型的数组,这个数组包含多种类型的结果。

变量

在 GraphQL 中,联合类型也可以用于定义变量类型,这样变量就可以接受多种类型的输入。

-- -------------------- ---- -------
----- ----------------- -
  --- ---
  ----- -----------------
-

---- ---------------- -
  ----
  -----
-

---- -------- -
  -------------------------- -------------------- -------------
-

在上面的示例中,SearchResultInput 是一个输入类型,包含 idtype 两个字段,其中 type 的类型是枚举类型 SearchResultType,这个枚举类型包含了 USERMOVIE 两个值,用于区分联合类型的不同类型。updateSearchResult 是一个更新类型,参数 result 的类型是 SearchResultInput,返回类型是 SearchResult

联合类型在查询结果中的定义

在 GraphQL 中,查询结果必须声明出所有可能的返回值类型,以便客户端进行类型推断。在联合类型中,我们可以使用关键词 ...on 来列举出联合类型中包含的所有类型。

假设我们要实现一个简单的搜索引擎,查询结果为 UserMovie,并且在前端中需要根据不同的类型分别显示不同的信息。在这种情况下,我们可以使用 ...on 定义不同的类型。

-- -------------------- ---- -------
----- -------------- -------- -
  ------------- ------- -
    --- -- ---- -
      --
      ----
    -
    --- -- ----- -
      --
      -----
    -
  -
-

在上面的查询中,$query 是查询参数,查询 search 返回的结果包含多种类型,使用 ... on 列举出不同类型的字段。当客户端请求时,服务器根据查询参数,决定返回的结果是 User 还是 Movie

手动处理联合类型

虽然 ... on 可以帮我们自动处理联合类型,但是有时候我们需要手动操作联合类型,这时候就需要了解 GraphQL 中的一些内置函数。以下是一些常用的内置函数。

  • __typename:返回当前对象的类型名称,用于区分联合类型的不同类型。
  • __typename... on 结合使用,用于手动处理联合类型。

例如:

-- -------------------- ---- -------
-
  ------------- -------- -
    ----------
    --- -- ---- -
      --
      ----
    -
    --- -- ----- -
      --
      -----
    -
  -
-

在上面的查询中,我们手动添加了 __typename 对象,并将 UserMovie 两种类型分开进行处理。

联合类型的最佳实践

在实际开发中,为了使联合类型更加灵活和易用,我们需要遵循一些最佳实践。

统一命名规范

联合类型可能包含多种不同的类型,其中每种类型都可能有自己的属性和方法。为了方便客户端进行开发和维护,我们需要对不同类型的属性和方法进行统一的命名规范。

例如:假设我们要定义一个联合类型 SearchResult,其中包含多种类型:UserMovie。为了方便客户端直接使用类型的属性和方法,我们需要为每个类型编写特定的方法,用于统一属性和方法的名称。

-- -------------------- ---- -------
----- ------------ - ---- - -----

---- ----- -
  ------------- --------- ----------------
-

---- ---- -
  --- ---
  ----- -------
-

---- ----- -
  --- ---
  ------ -------
-

--------- --------------------- -
  --- ---
  ----- -------
  ------ -------
-

---- ---------------- ---------- --------------------- -
  --- ---
  ----- -------
  ------ -------
  ----------- -------
-

---- ----------------- ---------- --------------------- -
  --- ---
  ----- -------
  ------ -------
  ----------- -------
-

---- -------------------- -
  ----------- -------
  ----- ----------------------
-

---- ----- -
  ------------- --------- ------------------------
-

在上面的示例中,我们为每个类型定义了一个 SearchResultInterface 接口,这个接口包含三个字段:idnametitleSearchResultUserSearchResultMovieSearchResult 联合类型中的具体类型,分别用于表示 UserMovie 两种类型。

最后,我们还定义了一个 SearchResultListItem 类型,它包含一个 __typename 字段和一个 data 字段,用于向客户端返回数据。

对数据集合进行分类

在设计联合类型时,我们应该遵循 聚合(composition) 模式,即将不同类型的数据集合进行分类。具体来说,将不同类型的数据集合放在不同的 GraphQL 对象中,然后再定义一个联合类型来引用这些对象。

例如:假设我们有两个数据集合:UserMovie。这两个数据集合虽然拥有相同的字段,但是它们是完全不同的对象,用于不同的场景。在这种情况下,我们应该将它们放在不同的对象中,然后再定义一个联合类型 SearchResult 引用这些对象。

-- -------------------- ---- -------
---- ----- -
  ----------------- --------- --------
  ------------------ --------- ---------
-

---- ---- -
  --- ---
  ----- -------
-

---- ----- -
  --- ---
  ------ -------
-

----- ------------ - ---- - -----

---- ----- -
  ------------- --------- ----------------
-

在上面的示例中,我们将 UserMovie 放在不同的对象中,然后再定义了一个联合类型 SearchResult,用于表示这两种类型之间的相似性。

避免类型耦合

为了避免类型耦合,我们需要将联合类型和接口进行分离,避免将联合类型和某个具体接口耦合在一起。这样可以增加代码的维护性,并更容易添加新的类型。

例如:假设我们有两个数据集合:UserMovie,它们都有各自的属性和方法。为了避免将联合类型和某个具体接口耦合在一起,我们需要将 UserMovie 分别放在不同的对象中,然后再定义两个接口 UserInterfaceMovieInterface,用于定义属性和方法。最后定义一个联合类型 SearchResult 引用这两个接口。

-- -------------------- ---- -------
--------- ------------- -
  --- ---
  ----- -------
  ------ ------
-

--------- -------------- -
  --- ---
  ------ -------
  ------ ------
-

---- ---- ---------- ------------- -
  --- ---
  ----- -------
  ------ ------
-

---- ----- ---------- -------------- -
  --- ---
  ------ -------
  ------ ------
-

----- ------------ - ------------- - --------------

---- ----- -
  ------------- --------- ----------------
-

在上面的示例中,我们将 UserMovie 分别放在不同的对象中,然后定义了两个接口 UserInterfaceMovieInterface,用于定义属性和方法。最后定义一个联合类型 SearchResult 引用这两个接口。

结论

联合类型是 GraphQL 中非常重要的一种数据类型,它可以让我们更加灵活地处理具有多样性的数据集合。要善于运用联合类型,我们需要了解联合类型的基本知识和使用技巧,同时还需要遵循一些最佳实践,例如统一命名规范、对数据集合进行分类、避免类型耦合等。只有这样,我们才能更加灵活地使用 GraphQL 接口,更好地提供服务。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/671da2649babaf620fb7501c

纠错
反馈