You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There have been many threads on different issues and pull requests regarding this feature. The main discussion started with the graphql/graphql-js#207 on 17/10/2015.
Currently, GraphQL input types can only have one single definition, and the more adoption GraphQL gained in the past years it has become clear that this is a serious limitation in some use cases. Although there have been multiple proposals in the past, this is still an unresolved issue.
With this RFC document, I would like to collect and summarise the previous discussions at a common place and proposals and propose a new alternative solution.
To have a better understanding of the required changes there is a reference implementation of this proposal, but that I will keep up to date based on future feeback on this proposal.
The following list shows what proposals have been put forward so far including a short summary of pros and cons added by @treybrisbane in this comment
This proposal was the first official RFC which has been discussed at the last GraphQL Working Group meeting.
This proposal in this current form has been rejected by the WG because of the __inputname semantics. However, everyone agrees that alternative proposals should be explored.
Pros:
Expresses the design intent within the schema
Supports unions of types with overlapping fields
Removes the costs of the tagged union pattern (both to the schema and field resolution)
Addresses the feature asymmetry of unions within the type system
Cons:
Adds complexity to the language in the form of input union-specific syntax
Adds complexity to the language in the form of additional validation (around __inputtype, etc)
Adds complexity to the request protocol in the form of a (input union-specific) constraint
Requires no language or request prototcol changes beyond a new directive
Supports unions of types with overlapping fields
Cons:
Adds complexity to the language in the form of a new directive
Does not express the design intent within the schema (the presence of a directive completely changes the meaning of a type definition which would otherwise be used to describe a simple object type)
Does not remove the costs of the tagged union pattern
Does not address the feature asymmetry of unions within the type system
Proposed solution
Based on the previous discussions I would like to propose an alternative solution by using a disjoint (or discriminated) union type.
Defining a disjoint union has two requirements:
Have a common literal type field - called the discriminant
A type alias that takes the union of those types - the input union
{"content": [{"kind": "PostInputKind","title": "My Post","body": "Lorem ipsum ...",},{"kind": "ImageInputKind","photo": "http://www.tanews.org.tw/sites/default/files/imce/admin/user2027/6491213611_c4fc290a33_z.jpg","caption": "Dog"}]}
New types
Literal type
The GraphQLLiteralType is an exact value type. This new type enables the definition a discriminant field for input types that are part of an input union type.
Input union type
The GraphQLInputUnionType represent an object that could be one of a list of GraphQL Input Object types.
Input Coercion
The input union type needs a way of determining which input object a given input value correspond to. Based on the discriminant field it is possible to have an internal function that can resolve the correct GraphQL Input Object type. Once it has been done, the input coercion of the input union is the same as the input coercion of the input object.
Type Validation
Input union types have a potential to be invalid if incorrectly defined:
An input union type must include one or more unique input objects
Every included input object type must have:
One common field
This common field must be a unique Literal type for every Input Object type
Using String or Enum types instead of Literal types
While I think it would be better to add support for a Literal type, I can see that this type would only be useful for Input unions; therefore, it might be unnecessary. However, it would be possible to use String or Enum types for the discriminant field, but in this case, a resolveType function must be implemented by the user. This would also remove one of the type validations required by the input type (2.2 - The common field must be a unique Literal type for every Input Object type).
Final thoughts
I believe that the above proposal addresses the different issues that have been raised against earlier proposals. It introduces additional syntax and complexity but uses a concept (disjoint union) that is widely used in programming languages and type systems. And as a consequence I think that the pros of this proposal outweigh the cons.
Pros
Expresses the design intent within the schema
The discriminant field name is configurable
Supports unions of types with overlapping fields
Addresses the feature asymmetry of unions within the type system
Does not require changes to the request protocol
Cons
Adds complexity to the language in the form of literal-specific syntax (might not need)
Adds complexity to the language in the form of input union-specific syntax
Adds complexity to the language in the form of additional validations (input union, discriminant field, input union resolving (might not need))
However, I think there are many questions that needs some more discussions, until a final proposal can be agreed on - especially around the new literal type, and if it is needed at all.
[RFC] GraphQL Input Union type
Background
There have been many threads on different issues and pull requests regarding this feature. The main discussion started with the graphql/graphql-js#207 on 17/10/2015.
Currently, GraphQL input types can only have one single definition, and the more adoption GraphQL gained in the past years it has become clear that this is a serious limitation in some use cases. Although there have been multiple proposals in the past, this is still an unresolved issue.
With this RFC document, I would like to collect and summarise the previous discussions at a common place and proposals and propose a new alternative solution.
To have a better understanding of the required changes there is a reference implementation of this proposal, but that I will keep up to date based on future feeback on this proposal.
The following list shows what proposals have been put forward so far including a short summary of pros and cons added by @treybrisbane in this comment
__inputnamefield by @tgriesserRFC document: RFC: inputUnion type #395
Reference implementation: RFC: inputUnion type graphql-js#1196
This proposal was the first official RFC which has been discussed at the last GraphQL Working Group meeting.
This proposal in this current form has been rejected by the WG because of the
__inputnamesemantics. However, everyone agrees that alternative proposals should be explored.Tagged union by @leebyron and @IvanGoncharov
Original comment
Directive
Original comment
Proposed solution
Based on the previous discussions I would like to propose an alternative solution by using a disjoint (or discriminated) union type.
Defining a disjoint union has two requirements:
With that our GraphQL schema definition would be the following (Full schema definition)
And a mutation query would be the following:
or with variables
New types
Literal type
The GraphQLLiteralType is an exact value type. This new type enables the definition a discriminant field for input types that are part of an input union type.
Input union type
The GraphQLInputUnionType represent an object that could be one of a list of GraphQL Input Object types.
Input Coercion
The input union type needs a way of determining which input object a given input value correspond to. Based on the discriminant field it is possible to have an internal function that can resolve the correct GraphQL Input Object type. Once it has been done, the input coercion of the input union is the same as the input coercion of the input object.
Type Validation
Input union types have a potential to be invalid if incorrectly defined:
Using String or Enum types instead of Literal types
While I think it would be better to add support for a Literal type, I can see that this type would only be useful for Input unions; therefore, it might be unnecessary. However, it would be possible to use String or Enum types for the discriminant field, but in this case, a
resolveTypefunction must be implemented by the user. This would also remove one of the type validations required by the input type (2.2 - The common field must be a unique Literal type for every Input Object type).Final thoughts
I believe that the above proposal addresses the different issues that have been raised against earlier proposals. It introduces additional syntax and complexity but uses a concept (disjoint union) that is widely used in programming languages and type systems. And as a consequence I think that the pros of this proposal outweigh the cons.
Pros
Cons
However, I think there are many questions that needs some more discussions, until a final proposal can be agreed on - especially around the new literal type, and if it is needed at all.