Taking this scheme:
union Vehicle = Airplane | Car
type Airplane {
title: String
wingSpan: Int
}
type Car {
title: String
wheels: Int
}
type Person {
vehicle: [Vehicle!]
}
With this query:
person {
vehicles {
... on Car {
title
wheels
}
... on Airplane {
title
wingSpan
}
}
}
And these resolvers:
// vehicle-resolver.js
export default {
Vehicle: {
__resolveType(obj) {
if (obj.wheels) {
return "Car"
} else {
return "Airplane"
}
}
}
}
// person-resolver.js
export default {
Person: {
vehicles(obj, args, context) {
// Am I resolving a car or an airplane now - or even both?
// I need to ask my CarService with `obj.personId` or my AirplaneService also with `obj.personId` but I only want to query it if the query is asking for it.
}
}
}
My question is that on my Person -> vehicles(...) I am unsure when I should query my service for getting the cars and when I should query my service for finding airplanes - or both?
The vehicles(...) does not give any information on what type(s) it tries to resolve?
If I understand your question correctly, you should query both and return all cars and airplanes that fits to the Person's vehicles query.
Then the __resolveType resolver would run for each result to provide GraphQL with the right type for each result.
Then with that information GraphQL would be able to return to the client the right selection set for each result.
Few things to make clear just to make sure we are on the same page:
The client does not determine if it queries for a specific type and doesn't know what type it will get, that's why the client places a query that handles both cases.
The vehicles resolver will return an array that may include all types on the union, the client's inline fragments as a switch/case statement for each result and the __resolveType resolver as providing the switch/case statement with the condition variable for each result.
If in the vehicles resolver you already know what the type of each result is, you can attach it to the result and simply return it in the __resolveType resolver but sometimes that creates complexity as those results will go through the whole resolver tree of the query and might affect logic in other resolvers.
So keep the logic inside __resolveType can help to keep handling union types logic contained in one place.
Maybe I wrote too much things you already knew, so let me know if that's not your question at all :)
Most helpful comment
If I understand your question correctly, you should query both and return all cars and airplanes that fits to the Person's vehicles query.
Then the
__resolveTyperesolver would run for each result to provide GraphQL with the right type for each result.Then with that information GraphQL would be able to return to the client the right selection set for each result.
Few things to make clear just to make sure we are on the same page:
The client does not determine if it queries for a specific type and doesn't know what type it will get, that's why the client places a query that handles both cases.
The
vehiclesresolver will return an array that may include all types on the union, the client's inline fragments as a switch/case statement for each result and the__resolveTyperesolver as providing the switch/case statement with the condition variable for each result.If in the
vehiclesresolver you already know what the type of each result is, you can attach it to the result and simply return it in the__resolveTyperesolver but sometimes that creates complexity as those results will go through the whole resolver tree of the query and might affect logic in other resolvers.So keep the logic inside
__resolveTypecan help to keep handling union types logic contained in one place.Maybe I wrote too much things you already knew, so let me know if that's not your question at all :)