解决 GraphQL 在 JavaScript 中的类型不匹配问题

阅读时长 6 分钟读完

最近,很多使用 GraphQL 的前端开发者都遇到了一个问题:使用 Apollo Client 发送请求时,返回数据类型与定义的类型(比如 TypeScript 的类型或者 JavaScript 类型)不匹配。这个问题会导致编译时错误,也可能导致运行时错误,特别是在处理复杂的数据类型时,更容易发生这种情况。在本文中,我们将讨论这个问题,并提供一些解决方案。

问题的根源

GraphQL 是一种类型系统,它定义了查询语言和类型规范。使用 GraphQL 和 Apollo Client,我们可以定义查询和类型规范,然后发送请求到后端,获取返回的数据并进行处理。在处理返回的数据时,我们可能需要将它们映射到前端的类型规范中。

问题在于,GraphQL 返回的数据是 JSON 格式的,而 JavaScript 的数据类型是动态的,这就可能导致类型不匹配的问题。比如,我们定义了一个 TypeScript 接口:

然后,我们定义了一个查询,可以获取后端返回的用户信息:

如果我们使用 Apollo Client 发送这个查询并在 TypeScript 中处理返回的数据,可能会遇到类型不匹配的问题。因为返回的数据结构是这样的:

注意,"age" 的值是一个字符串而不是一个数字。这会导致 TypeScript 报错,因为我们定义的 User 接口中,age 的类型是 number,而返回的数据中是 string 类型。

解决方案

有几种解决方案可以解决这个问题。

1. 手动映射数据

第一种解决方案是手动映射返回的数据。我们可以使用 Apollo Client 提供的 useQuery 钩子来获取数据,并在钩子中对返回的数据进行处理和映射。比如,我们可以这样定义 useUser

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

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

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

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

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

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

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

在这个钩子中,我们首先使用 useQuery 获取数据。然后,我们判断数据是否存在和是否正在加载中。如果有错误,我们抛出错误。最后,我们手动映射返回的数据,将 "age" 转换为 number 类型。

这种方法的优点是灵活,可以根据需要对返回的数据进行任何处理。缺点是需要手动编写映射逻辑,并且可能会造成冗余代码。

2. 使用类型转换库

第二种解决方案是使用类型转换库。这种库可以自动将 JSON 数据转换为 JavaScript 类型,并且支持与 TypeScript 或 Flow 等类型检查器集成。比如,我们可以使用 json-typescript-mapper 这个库,定义一个映射配置:

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

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

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

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

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

在这个配置中,我们定义了一个 User 类型和一个 JsonConvert 实例。首先,我们将 ignorePrimitiveChecks 设为 false,这样可以确保每个变量都有明确的类型。然后,我们将 valueCheckingMode 设为 ALLOW_NULL,这样我们可以处理一些可能为 null 的变量。最后,我们定义了一个 User 类型的映射,将 "age" 属性映射为一个数字类型的值。

有了这个映射配置之后,我们就可以使用它将返回的数据转换为我们定义的类型了:

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

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

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

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

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

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

在这个钩子中,我们首先使用 useQuery 获取数据,然后判断数据是否存在和是否正在加载中。如果有错误,我们抛出错误。最后,我们使用 jsonConvert 将返回的数据转换为我们定义的 User 类型。

这种方法的优点是自动化程度高,并且可以避免冗余代码。缺点是需要使用第三方库,可能会增加项目的依赖。此外,这种方法不能完全取代手动映射的方法,因为有些数据可能需要特殊处理。

结论

GraphQL 在 JavaScript 中的类型不匹配问题是一个常见的问题。我们可以使用手动映射或者类型转换库等方法来解决这个问题。手动映射方法灵活但可能会冗余代码,类型转换库则可以自动化程度高但需要使用第三方库。在实际开发中,我们可以选择最适合自己项目的方法,来处理这个问题。

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

纠错
反馈