Skip to content

Commit

Permalink
Support empty composite types
Browse files Browse the repository at this point in the history
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 graphql#490). This allows defining an empty `Query` object type, while still supporting introspection.
- Support for algebraic data types (see graphql#568), where `__typename` is the only relevant field
- Potentially to support "well-known" (but empty) extensions of the introspection schema (see graphql#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 0599414.
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 graphql#568 and graphql#490 at the specification level.
  • Loading branch information
victorandree committed Aug 5, 2019
1 parent 22feb9c commit 0db4cdd
Showing 1 changed file with 5 additions and 8 deletions.
13 changes: 5 additions & 8 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 0db4cdd

Please sign in to comment.