Closed benjie closed 1 year ago
Name | Link |
---|---|
Latest commit | 3311df377efc6eef5438d2670a4baae8c6932ecc |
Latest deploy log | https://app.netlify.com/sites/graphql-spec-draft/deploys/650cd1b4e6e0f500080d720a |
First of all, thanks for kicking off the discussion. I think this proposal gets us what we will need for True Nullabilty, and severs as a great starting place for iteration.
Mainly the syntax has some drawbacks ( perhaps we should defer syntax bike shedding for another time, but I’ll list a few concerns for now)
An observation: we’ll also need to consider how this new type variant would affect interface validation and potentially selection validation.
I agree on all your points @captbaritone. From a separate in-person conversation, I think @mjmahone thinks that this new "non-nullable error boundary" type should be the default, but I'm not convinced I agree - I think nullable+null boundary (i.e. the current default) should remain the default.
Also, I'm considering changing it into a different "wrapper type" instead. So these spec edits are far from complete.
Agree that the syntax is a bit weird. Is !?
used in any other language?
Also the list case is always a bit awkward:
type User {
friends: [User!?]!?
}
But overall, what bugs my brain the most here is that it introduces some kind of dissymmetry between nullable and non-nullable types. Why would error boundaries be limited to non-nullable types?
I get the technical reason why (null bubbling is only an issue for non-nullable fields). But from a user point of view, I'd expect errors and nullability to be orthogonal concepts. If we're saying !?
is an indication that a non-nullable field might error, I would almost expect a symmetrical ??
that hints that the given nullable field might error. But maybe it's too much?
Yeah, so what I’m considering is that you’d have e.g. errorBoundary(nonNullable(Int))
which would come out as Int!?
. The problem right now is that error boundaries are implicit, so this would have a pretty tough migration story for schemas.
To clarify, with this schema:
type Query {
book: Book!?
}
type Book {
author: User!?
}
querying book
when the author
resolver fails, would return:
a/
{ "errors": {...}, "data": { "book": { "author": null } } }
or b/
{ "errors": {...}, "data": { "book": null } }
?
(A) (there is no bubbling past an interrobang )
Closing this in favour of the much more complete asterisk proposal: https://github.com/graphql/graphql-spec/pull/1048
Inspired by @captbaritone's True Nullability Schema discussion (https://github.com/graphql/graphql-wg/discussions/1394) and following @fotoetienne's excellent talk at GraphQLConf, and trying to "use the things we already have in new ways" I am proposing that we introduce a new non-nullable variant, the "Non-Null error boundary" type, represented via interrobang mark
!?
. This will be aNon-Null
type in the current sense, but with an extra property of__Type.isErrorBoundary: true
Critically, this type would "evaporate" for legacy clients, appearing the same as a nullable field. (This is enabled via the
includeErrorBoundaries
argument to the__Field.type
field, which defaults tofalse
.)The main difference in this type is that it will never be
null
unless there is an error in theerrors
array. So it's like a hybrid between the nullability default, and Non-Null. A middle ground.I have not made all the spec edits for this, I'm just feeling out the problem space right now. "Collecting" the field error (rather than throwing it) is going to need some careful wording... but that's a problem for when we come to formalize it.