From 0db4cdd3f48048c5caef4077abca24e00eda79cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Andr=C3=A9e?= Date: Mon, 5 Aug 2019 16:49:33 +0200 Subject: [PATCH] Support empty composite types Supporting empty types, e.g. objects, input objects and interfaces without any fields, has concrete use cases. - Support for GraphQL APIs without any `Query` operation type fields, for example, if the API only support mutations or subscriptions (see #490). This allows defining an empty `Query` object type, while still supporting introspection. - Support for algebraic data types (see #568), where `__typename` is the only relevant field - Potentially to support "well-known" (but empty) extensions of the introspection schema (see #300) This is a minimalist spec change, which simply removes the relevant items under the type validation sub sections. It would probably be helpful to motivate the change and mention that one or more fields _should_ be present for a (typically) useful schema. The requirement for composite types (object, input objects and interfaces) to define "one or more fields" was introduced in 059941486fcea9b93c5a156fe80df03d2021c0b4. This change references graphql/graphql-js#368, motivating the change with: > Since GraphQL always requires you to select fields down to scalar values, an Object type without any defined fields cannot be accessed in any way in a query. > This could be even more problematic for Input Objects where a required input object argument with no fields could result in a field that is impossible to query without producing an error. With regards to these objections: - It's always possible to select `__typename` and therefore even empty object types can be useful (as e.g. algebraic data types) - Passing an empty input object appears syntactically valid: ```gql mutation { update(input: {}) { name } } ``` I think this proposal fulfills the guiding principles by enabling new capabilities motivated by real use cases. This change does not make any previously valid schema invalid, so largely preseves backwards compatibility. Fixes #568 and #490 at the specification level. --- spec/Section 3 -- Type System.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index a7df96e01..a6a2e09b4 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -792,8 +792,7 @@ Objects are never valid inputs. Object types have the potential to be invalid if incorrectly defined. This set of rules must be adhered to by every Object type in a GraphQL schema. -1. An Object type must define one or more fields. -2. For each field of an Object type: +1. For each field of an Object type: 1. The field must have a unique name within that Object type; no two fields may share the same name. 2. The field must not have a name which begins with the @@ -804,8 +803,8 @@ of rules must be adhered to by every Object type in a GraphQL schema. characters {"__"} (two underscores). 2. The argument must accept a type where {IsInputType(argumentType)} returns {true}. -4. An object type may declare that it implements one or more unique interfaces. -5. An object type must be a super-set of all interfaces it implements: +2. An object type may declare that it implements one or more unique interfaces. +3. An object type must be a super-set of all interfaces it implements: 1. The object type must include a field of the same name for every field defined in an interface. 1. The object field must be of a type which is equal to or a sub-type of @@ -1052,8 +1051,7 @@ Interfaces are never valid inputs. Interface types have the potential to be invalid if incorrectly defined. -1. An Interface type must define one or more fields. -2. For each field of an Interface type: +1. For each field of an Interface type: 1. The field must have a unique name within that Interface type; no two fields may share the same name. 2. The field must not have a name which begins with the @@ -1410,8 +1408,7 @@ Literal Value | Variables | Coerced Value **Type Validation** -1. An Input Object type must define one or more input fields. -2. For each input field of an Input Object type: +1. For each input field of an Input Object type: 1. The input field must have a unique name within that Input Object type; no two input fields may share the same name. 2. The input field must not have a name which begins with the