-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Modeling certain tagged unions in GraphQL #489
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
GraphQL current have no support for sum types, so you are more or less forced to simulate them somehow. If you are lucky, your Cash, CC and Paypal all have identity so they contain an In a sense, your "Cash" is a phantom type, since it cannot have any inhabitant in the system. I'm not sure how this would be useful to a client. So perhaps you can explain the need from the clients perspective to model the data like this (either by means of this example, or a new one). |
This comment has been minimized.
This comment has been minimized.
I'm open to modeling things in a different way in the schema given the lack of support for sum types, I'm just not sure what to do in cases like this where an element of the sum type carries no additional data other than their type. If the cash example is too contrived, consider modeling search filters: // maybe these are search filters for an apartment search service
// represented here in TypeScript (might be valid Flow too?)
type SearchFilter = PriceFilter | NeighborhoodFilter | HasImageFilter;
interface PriceFilter {
type: "price";
minPrice?: number;
maxPrice?: number;
}
interface NeighborhoodFilter {
type: "neighborhood";
neighborhood: string;
}
interface HasImageFilter {
type: "has_image";
// there's no additional data here, the type says it all
} I'm mostly trying to understand if there are best practices around modeling situations like this in GraphQL. The search filter case is maybe a better example because you probably would want to specify these types as an input to a query, and input types don't even support unions (#488). The only way I could imagine modeling that case as inputs would be: enum SearchFilterType {
PRICE
NEIGHBORHOOD
HAS_IMAGE
}
input SearchFilter {
type: SearchFilterType!
# only set if type == PRICE
minPrice: Number
maxPrice: Number
# only set if type == NEIGHBORHOOD
neighborhood: String
} Which honestly feels pretty bad. |
I think providing an enum is a reasonable step, or just provide some useless field to fulfill the validation requirements. If you think it's a common enough case, you could propose removing the rule that object types require at least one field - though that often protects against accidental cases where fields are forgotten. For the search filter, that's been discussed as input unions elsewhere. I think having literal string types to allow for sum-types for input unions is probably a better implementation than other proposals so far. If you're willing, I encourage you to create RFCs for these ideas if you can see them through. |
Hi, @leebyron wonder if there is an issue somewhere about using scalar instances as types directly? For example, using string literals directly:
What I'm looking for is mostly to have codegen tools being able to generate correct TS typings, using a discriminent, so that doing |
@slorber That's normally solved by using the |
ah yeah thanks ;) |
Apologies if this is the wrong place to ask this kind of question, but I was hoping to get some advice on how to model a specific scenario in my GraphQL schema. Let's say in my application I'm modeling a user's payment method as follows (this scenario is hypothetical, all that matters is that some of the members of the tagged union have no fields other than the discriminator):
What would be the right way to model this in GraphQL? I would initially try:
But this violates the spec, because object types are required to have one or more fields. I suppose I could throw a type field on there, but it's redundant - I would actually want to query
__typename
. Is there a better way to model this in GraphQL?The text was updated successfully, but these errors were encountered: