I use the following convention to let resolvers return partial data, and allow other resolvers complete the missing fields:
type UserExtra {
name: String!
}
type User {
id: ID!
email: String!
extra: UserExtra!
}
type Query {
user(id: ID!): User!
users: [User!]!
}
const getUser = (id: string): { id: string, email: string, extra: { name: string } => fetchUser(id);
// `fetchUsers` only returns `id` and `email`, but not `extra`
const getUsers = (): { id: string, email: string }[] => fetchUsers();
// we can use this function to fetch the extra field for a given user
const getUserExtra = (id: string): { name: string } => fetchUserExtra();
export default {
Query: {
user: (parent, args) => getUser(args.id),
users: () => getUsers(),
},
User: {
// here we fetch the `extra` field anytime an `User` is requested
// in real-life I would check if the query is requesting the `extra`
// field or not, and only fetch the data if requested by the query
extra: (parent) => {
return getUserExtra(parent.id)
},
}
}
The problem I'm having is that GraphQL Code Generator generates a Resolver
type that expects Query#users
to return the complete User
shape, and of course it's not aware of the fact that even though I return a partial shape from Query#users
, thanks to User#extra
the client will end up receiving the expected shape nonetheless.
What's the best approach to handle this case while keeping TS happy?