GraphQL 中输入类型的重点是什么? [英] What's the point of input type in GraphQL?

查看:19
本文介绍了GraphQL 中输入类型的重点是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你能解释一下为什么如果mutation的输入参数是object它应该是输入类型?我认为更简单的只是重用 type 而不提供 id.

Could you please explain why if input argument of mutation is object it should be input type? I think much simpler just reuse type without providing id.

例如:

type Sample {
  id: String
  name: String
}

input SampleInput {
  name: String
}

type RootMutation {
  addSample(sample: Sample): Sample  # <-- instead of it should be
  addSample(sample: SampleInput): Sample
}

对于小对象来说没问题,但是当您在架构中有大量具有 10 多个属性的对象时,这将成为负担.

It's okay for small object, but when you have plenty of objects with 10+ properties in schema that'll become a burden.

推荐答案

来自规范:

GraphQL 对象类型 (ObjectTypeDefinition)... 不适合重用 [作为输入],因为对象类型可以包含定义参数的字段或包含对接口和联合的引用,这两者都不适合用作一个输入参数.因此,输入对象在系统中具有单独的类型.

The GraphQL Object type (ObjectTypeDefinition)... is inappropriate for re‐use [as an input], because Object types can contain fields that define arguments or contain references to interfaces and unions, neither of which is appropriate for use as an input argument. For this reason, input objects have a separate type in the system.

这是官方原因",但有几个实际原因为什么不能使用对象类型作为输入对象类型或使用对象类型作为输入对象类型:

That's the "official reason", but there's several practical reasons why you can't use an object type as an input object type or use an object type as an input object type:

对象类型和输入对象类型都具有字段,但是这些字段具有反映架构如何使用这些类型的不同属性.您的架构可能会为对象类型的字段定义参数和某种解析器函数,但这些属性在输入上下文中没有意义(即您不能解析输入对象的字段——它已经有一个明确的价值).同样,只能为输入对象类型字段提供默认值,而不能为对象类型字段提供默认值.

Object types and input object types both have fields, however those fields have different properties that reflect how these types are used by the schema. Your schema will potentially define arguments and some kind of resolver function for an object type's fields, but these properties don't make sense in an input context (i.e. you can't resolve an input object's field -- it already has an explicit value). Similarly, default values can only be provided for input object type fields, and not object type fields.

换句话说,这看起来像是重复:

In other words, this may seem like duplication:

type Student {
  name: String
  grade: Grade
}

input StudentInput {
  name: String
  grade: Grade
}

但是添加特定于对象类型或输入对象类型的功能可以清楚地表明它们的行为不同:

But adding features specific to either object types or input object types makes it clear that they behave differently:

type Student {
  name(preferred: Boolean): String
  grade: Grade
}

input StudentInput {
  name: String
  grade: Grade = F
}

类型系统限制

GraphQL 中的类型分为输出类型输入类型.

输出类型是可以作为 GraphQL 服务生成的响应的一部分返回的类型.输入类型是字段或指令参数的有效输入类型.

Output types are types that may be returned as part of a response produced by a GraphQL service. Input types are types that are valid inputs for field or directive arguments.

这两个组(即标量、枚举、列表和非空值)之间存在重叠.然而,像联合和接口这样的抽象类型在输入上下文中没有意义,不能用作输入.分离对象类型和输入对象类型可以确保在需要输入类型的地方永远不会使用抽象类型.

There's overlap between these two groups (i.e. scalars, enums, lists and non-nulls). However, abstract types like unions and interfaces don't make sense in an input context and cannot be used as inputs. Separating object types and input object types allows you to ensure that an abstract type is never used where an input type is expected.

在您的架构中表示实体时,某些实体可能确实会在其各自的输入和输出类型之间共享字段":

When representing an entity in your schema, it's likely that some entities will indeed "share fields" between their respective input and output types:

type Student {
  firstName: String
  lastName: String
  grade: Grade
}

input StudentInput {
  firstName: String
  lastName: String
  grade: Grade
}

但是,对象类型可以(并且实际上经常这样做)对非常复杂的数据结构进行建模:

However, object types can (and in reality frequently do) model very complex data structures:

type Student {
  fullName: String!
  classes: [Class!]!
  address: Address!
  emergencyContact: Contact
  # etc
}

虽然这些结构可能翻译成适当的输入(我们创建了一个学生,所以我们也传递了一个代表他们地址的对象),但通常他们不会——即也许我们需要指定学生的类 ID 和部分 ID,而不是一个对象.类似地,我们可能有想要返回但不想改变的字段,反之亦然(例如 password 字段).

While these structures may translate into appropriate inputs (we create a Student, so we also pass in an object representing their address), often they do not -- i.e. maybe we need to specify the student's classes by class ID and section ID, not an object. Similarly, we may have fields that we want to return, but don't want to mutate, or vice versa (like a password field).

此外,即使对于相对简单的实体,我们经常对对象类型及其对应"输入对象之间的可空性有不同的要求.通常我们想保证一个字段也将在响应中返回,但我们不想在我们的输入中使用相同的字段.例如,

Moreover, even for relatively simple entities, we often have different requirements around nullability between object types and their "counterpart" input objects. Often we want to guarantee that a field will also be returned in a response, but we don't want to make the same fields required in our input. For example,

type Student {
  firstName: String!
  lastName: String!
}

input StudentInput {
  firstName: String
  lastName: String
}

最后,在许多模式中,给定实体的对象类型和输入对象类型之间通常没有一对一的映射.一个常见的模式是为不同的操作使用不同的输入对象类型来进一步微调模式级输入验证:

Lastly, in many schemas, there's often not a one-to-one mapping between object type and input object type for a given entity. A common pattern is to utilize separate input object types for different operations to further fine-tune the schema-level input validation:

input CreateUserInput {
  firstName: String!
  lastName: String!
  email: String!
  password: String!
}

input UpdateUserInput {
  email: String
  password: String
}

所有这些示例都说明了一个重要点——虽然输入对象类型有时可能会反映对象类型,但由于业务需求,您不太可能在生产模式中看到这一点.

All of these examples illustrate an important point -- while an input object type may mirror an object type some of the time, you're much less likely to see that in production schemas due to business requirements.

这篇关于GraphQL 中输入类型的重点是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆