Skip to content

Commit

Permalink
Input & Output type definition (#462)
Browse files Browse the repository at this point in the history
Throughtout the spec we refer to input and output types but never clearly define them in a referenced section. This adds that section and removes the ad-hoc descriptions from elsewhere in the spec.

It also uses the formal algorithms in place of prose where relevant.

Finally it adds to the schema validation rules for Object, Interface, and Input Object fields / arguments.
  • Loading branch information
leebyron authored Jun 11, 2018
1 parent 385503e commit 6ff258f
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 21 deletions.
71 changes: 59 additions & 12 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,34 @@ referred to as "named types". A wrapping type has an underlying named type,
found by continually unwrapping the type until a named type is found.


### Input and Output Types

Types are used throughout GraphQL to describe both the values accepted as input
to arguments and variables as well as the values output by fields. These two
uses categorize types as *input types* and *output types*. Some kinds of types,
like Scalar and Enum types, can be used as both input types and output types;
other kinds types can only be used in one or the other. Input Object types can
only be used as input types. Object, Interface, and Union types can only be used
as output types. Lists and Non-Null types may be used as input types or output
types depending on how the wrapped type may be used.

IsInputType(type) :
* If {type} is a List type or Non-Null type:
* Let {unwrappedType} be the unwrapped type of {type}.
* Return IsInputType({unwrappedType})
* If {type} is a Scalar, Enum, or Input Object type:
* Return {true}
* Return {false}

IsOutputType(type) :
* If {type} is a List type or Non-Null type:
* Let {unwrappedType} be the unwrapped type of {type}.
* Return IsOutputType({unwrappedType})
* If {type} is a Scalar, Object, Interface, Union, or Enum type:
* Return {true}
* Return {false}


### Type Extensions

TypeExtension :
Expand Down Expand Up @@ -757,10 +785,16 @@ 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. The fields of an Object type must have unique names within that Object type;
no two fields may share the same name.
3. Each field of an Object type must not have a name which begins with the
characters {"__"} (two underscores).
2. 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
characters {"__"} (two underscores).
3. The field must return a type where {IsOutputType(fieldType)} returns {true}.
4. For each argument of the field:
1. The argument must not have a name which begins with the
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:
1. The object type must include a field of the same name for every field
Expand Down Expand Up @@ -834,7 +868,8 @@ May yield the result:
}
```

The type of an object field argument can be any Input type.
The type of an object field argument must be an input type (any type except an
Object, Interface, or Union type).


### Field Deprecation
Expand Down Expand Up @@ -1009,10 +1044,18 @@ 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. The fields of an Interface type must have unique names within that Interface
type; no two fields may share the same name.
3. Each field of an Interface type must not have a name which begins with the
characters {"__"} (two underscores).
2. 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
characters {"__"} (two underscores).
3. The field must return a type where {IsOutputType(fieldType)}
returns {true}.
4. For each argument of the field:
1. The argument must not have a name which begins with the
characters {"__"} (two underscores).
2. The argument must accept a type where {IsInputType(argumentType)}
returns {true}.


### Interface Extensions
Expand Down Expand Up @@ -1360,9 +1403,13 @@ Literal Value | Variables | Coerced Value
**Type Validation**

1. An Input Object type must define one or more input fields.
2. The fields of an Input Object type must have unique names within that
Input Object type; no two fields may share the same name.
3. The return types of each defined field must be an Input type.
2. 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
characters {"__"} (two underscores).
3. The input field must accept a type where {IsInputType(inputFieldType)}
returns {true}.


### Input Object Extensions
Expand Down
9 changes: 3 additions & 6 deletions spec/Section 5 -- Validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -1533,15 +1533,12 @@ fragment HouseTrainedFragment {
* For every {operation} in a {document}
* For every {variable} on each {operation}
* Let {variableType} be the type of {variable}
* While {variableType} is {LIST} or {NON_NULL}
* Let {variableType} be the referenced type of {variableType}
* {variableType} must be of kind {SCALAR}, {ENUM} or {INPUT_OBJECT}
* {IsInputType(variableType)} must be {true}

**Explanatory Text**

Variables can only be scalars, enums, input objects, or lists and non-null
variants of those types. These are known as input types. Objects, unions,
and interfaces cannot be used as inputs.
Variables can only be input types. Objects, unions, and interfaces cannot be
used as inputs.

For these examples, consider the following typesystem additions:

Expand Down
5 changes: 2 additions & 3 deletions spec/Section 6 -- Execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ CoerceVariableValues(schema, operation, variableValues):
* For each {variableDefinition} in {variableDefinitions}:
* Let {variableName} be the name of {variableDefinition}.
* Let {variableType} be the expected type of {variableDefinition}.
* Assert: {variableType} must be an input type.
* Assert: {IsInputType(variableType)} must be {true}.
* Let {defaultValue} be the default value for {variableDefinition}.
* Let {hasValue} be {true} if {variableValues} provides a value for the
name {variableName}.
Expand Down Expand Up @@ -556,8 +556,7 @@ ExecuteField(objectType, objectValue, fieldType, fields, variableValues):

Fields may include arguments which are provided to the underlying runtime in
order to correctly produce a value. These arguments are defined by the field in
the type system to have a specific input type: Scalars, Enum, Input Object, or
List or Non-Null wrapped variations of these three.
the type system to have a specific input type.

At each argument position in a query may be a literal {Value}, or a {Variable}
to be provided at runtime.
Expand Down

0 comments on commit 6ff258f

Please # to comment.