On a query like this
dishes {
... on RecipeDish {
id
recipeId
}
... on IngredientDish {
id
ingredient
}
}
The result is
export type Dishes = RecipeDishInlineFragment & IngredientDishInlineFragment
But it should be
export type Dishes = RecipeDishInlineFragment | IngredientDishInlineFragment
Am I not mistaken?
Thanks
Theoretically it should be the union I guess (|), but if it was, you would have neither ingredient nor recipeId available. It's kind of a trade off, but instead you have both of them.
@altschuler but a union implies that every element of dishes will have all three fields (id, recipeId, ingredient), when it's actually not true. Anyway a typeguard based on __typename should help..
@altschuler I wrote the comment above being sure that union is & instead of I %)
apollo-codegen produces a union for instance, however it doesn't generate it in a handy form this library does (with subtypes, instead of one long type), which makes it (apollo-codegen) not that useful
export type MenuDishFragmentFragment = {
dishes: Array<( {
__typename: "RecipeDish",
id: string,
recipeId: string,
} | {
__typename: "IngredientDish",
id: string,
ingredient: {
productId: string,
},
}
) >,
};
Yep, I think having the correct semantics of a union paired with the notion of __typename could be pretty powerful... does __typename get automatically appended to the response or is it something that has to be specifically selected?
@zephraph in apollo graphql express middleware __typename is appended always by default. I'm not sure for other implementations
I think that's the trick. We'd really need to check the spec just to be sure that's the default intent. I think it is... I'm not 100% sure though.
Here http://graphql.org/learn/queries/#meta-fields it says:
GraphQL allows you to request __typename, a meta field, at any point in a query to get the name of the object type at that point.
So look like it should only return __typename on request
I ran into a case where using & breaks. If the types in a union share a field name, but the type of the content of the field is different, it will throw an error stating that the fields are in conflict.
For example, we have an Activity type using the actor-verb-object structure. Object can be of any type we have in the app, and among the options it can be a Story or an Export. Story has a format which takes the values "Book", "Movie", "TV Show", etc, and Export's format field can be "pdf", "doc", etc. Both field are appropriately named for their usage, but when returning either of them using a union type the app will throw the error:
Fields "format" conflict because they return conflicting types StoryFormat! and ExportFormat!. Use different aliases on the fields to fetch both if this was intentional.
So I guess that it should be COMMON_FIELDS & (FRAGMENT | FRAGMENT | FRAGMENT) ?
What do you think? @iamdanthedev @altschuler @zephraph
ok, so I did some work on it, and the results will be: FIELDS & FRAGMENT_SPREAD & (INLINE_FRAGMENT | INLINE_FRAGMENT | INLINE_FRAGMENT).
Since fragment spread are in use to specify list of fields in a context of a type, and inline fragments are in use to declare different selection set for interface/union.
Fixed in 0.8.17 :)
Most helpful comment
@altschuler I wrote the comment above being sure that union is
&instead ofI%)apollo-codegenproduces a union for instance, however it doesn't generate it in a handy form this library does (with subtypes, instead of one long type), which makes it (apollo-codegen) not that useful