【问题标题】:Sequelize / Typescript / Graphql clashing on ID as Int vs StringSequelize / Typescript / Graphql 在 ID 上作为 Int 与 String 发生冲突
【发布时间】:2020-07-05 11:49:30
【问题描述】:

我创建了一个由 Sequelize 支持的 Apollo 服务器。

我也在用 TypeScript 编写我的应用程序。

这在 Sequelize 的主键(Int)概念与 GraphQL 的 ID(特殊字符串)概念之间产生了冲突。

具体来说,我有一个如下所示的 GQL 类型:

type Book {
    id: ID!
    Title: String!
  }

还有一个 Typescript 界面,大致如下:

export interface Book extends Model {
  id: number;
  name: string;
}

在我的解析器中,我有以下内容:

book: async (parent, args, context) => {
      const { models } = context;
      const { id } = args;
      const carrier = await models.Book.findByPk(id);
      return carrier;
    },

这会返回错误:

Types of property 'id' are incompatible.
                Type 'number' is not assignable to type 'string'.

这让我想到了我的问题

有没有办法强制 ID 解析为 int 而不是字符串?我想避免重新映射 Book 中的所有字段只是为了将 ID 转换为字符串

【问题讨论】:

  • 在graphql中使用Int类型而不是ID?
  • 我认为这会导致信息丢失。 ID 类型可以有程序化应用程序(比如在 Apollo 客户端缓存中),我不想丢失。

标签: typescript graphql sequelize.js


【解决方案1】:

没有办法改变标量的行为——它被解析为一个字符串,因为这是规范指定的。您可以像这样将字符串转换为标量:

await models.Book.findByPk(parseInt(id, 10));

但是,您也可以只使用Int 标量而不是ID。这种方法的最大缺点是,如果不对架构进行重大更改,您将无法切换到不同类型的 ID(如 UUID)。使用 Int 而不是 ID 不会影响 Apollo 客户端完成的缓存 - 只要该字段命名为 id_id,它将在缓存键中使用,无论其输入。

【讨论】:

  • 我的问题一定写得不清楚。我的问题不是解析传入的 int。问题是当我尝试序列化我的模型时,id 已经是 Int,但 gql 期望返回作为 ID,即字符串
  • 啊,你说的是响应。解析器可以为 ID 字段返回整数或字符串,因此听起来您在 TypeScript 中表示的 GraphQL 类型是错误的(即在 TS 中,该字段应键入为 string | number
  • 没错!但是,我使用这个 github.com/dotansimha/graphql-code-generator 来自动生成注释,因此必须使用遵循 ID 始终是字符串的 graphql 策略
  • 与其说是“政策”,不如说是bug with that library
  • 请参阅this section of the spec,了解为什么字符串或数字都可以接受的参考。无论如何,除非 GraphQL 代码生成器的问题得到解决,否则我建议坚持使用 Int 类型。除非您预计将来会更改数据库中的列类型,否则没有真正的缺点。
猜你喜欢
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 2012-09-26
  • 2013-11-26
  • 1970-01-01
  • 2018-08-24
相关资源
最近更新 更多