Description
You can read a fuller version of the RFC here.
TL;DR:
This RFC proposes new syntax for GraphQL clients to express that fields in an operation are non-null.
Problem Statement
The official best practice for schema design is to make all fields nullable by default. If “null” is not an appropriate value for a failed field, the guidance recommends making it nonNull in the SDL.
The problem with the SDL nonNull (!
) is that it eliminates the possibility of partial failure on a given type. This forces the schema author to decide for which fields partial failure is acceptable. A GraphQL schema author may not be in the best position to decide whether partial failure is acceptable for every possible use case.
Additionally, the answer to whether a missing value is acceptable may vary between UI canvases. Specifying nonNull (aka. required) in the query gives the UI developer the power to decide where partial failure is acceptable, and the flexibility for different canvases to have different requirements in this regard.
🧑💻 Proposed Solution
Three new operators are introduced to the query language:
- A "required designator" represented by
!
which marks a field Non-Nullable - An "optional designator" represented by
?
which marks a field Nullable - A "list operator" represented by
[]
which allows the above two operators to be applied to the elements of a list, or the list as a whole.
🎬 Behavior
The proposed query-side Non-Null designator and SDL-defined Non-Null would have slightly different behavior. When null is resolved for a SDL Non-Nullable field, the executor propagates until it finds the nearest Nullable parent, and sets that to null.
This proposal also introduces a second "optional designator", ?
, which designates that the field is Nullable, even if it is Non-Nullable in the schema. When null is resolved for a field marked with a required designator (!
) the executor instead propagates null to the nearest field marked with an optional designator (?
). If there is no optional designator to propagate to, then the response's data
field will become null ie the entire response will be lost. Because of that, in most cases we expect that required designators will be paired with optional designators to preserve partial responses.
✏️ Proposed syntax - !
The client can express that a schema field is required by using the !
syntax in the query definition:
query GetAllBusinesses {
businesses [!]? {
name!
}
}
We have chosen !
because !
is already being used in the GraphQL spec to indicate that a field in the schema is non-nullable. ?
chosen because other languages use it to indicate optionality. []
was used because it's traditionally been used to indicate a list.
If a field is a list, designators can either be applied directly to the field ie twoDListField!
or to the elements of the list with list operators matching the number of dimensions of the list ie twoDListField[[!]]!
.
✨ Use cases
Improve the developer experience using GraphQL client codegen types
Handling nullable values on the client is a major source of frustration for engineers, especially when using GraphQL codegen types in strongly-typed languages.
The proposed nonNull designator would allow GraphQL clients to generate codegen types with more precise nullability requirements for a particular feature. For example, using a GraphQL client like Apollo GraphQL on mobile, the following query
query GetBusinessName($id: String!) {
business(id: $id) {
name!
}
}
would codegen to the following type in Swift.
struct GetBusinessNameQuery {
let id: String
struct Data {
let business: Business?
struct Business {
/// Lack of `?` indicates that `name` will never be `null`
let name: String
}
}
}
If a null business name is not acceptable for the feature executing this query, this generated type is more ergonomic to use since the developer does not need to unwrap the value each time it’s accessed.