I know this example is contrived but assume that I have a data model that looks like this…
table Users ( id INT, userThing TEXT );
table Friend( id INT, friendThing TEXT);
table UsersToFriends( userId INT, friendId INT, friendMeta TEXT);
I then create a corresponding graphQL schema & resolver…
// schema.graphql
type User {
id: ID!
userThing: string
friends: FriendWithMeta[]
}
type Friend {
id: ID!
friendThing: string
}
type FriendWithMeta {
friendId!: ID!
friendMeta: string
friend: Friend
}
// resolver.ts
const resolvers: Resolvers = {
FriendWithMeta: {
friend: (friendWithMeta) => FriendService.getFriendById(friendWithMeta.friendId)
},
// This resolver is responsible for User fields including friends but does not resolve the sub "Friend" object which is handled in the field resolver above
User: (_root, { id }) => UserService.getUserWithFriendIdsByUserId(id)
}
export default resolvers;
Now if a client queries for User { friends { friendId, Friend { id }}
the friendId
which is included in FriendWithMeta
can be easily passed down into the field resolver to fetch the data for each friend.
The only issue I have with this is that the id of friend is repeated in the schema and can be confusing for clients who are introspecting it or viewing it’s documentation.
I’d like to eliminate the friendId
inside of FriendWithMeta
but without it the resolved typescript typing will not allow me to access the field.
Is there some trick I can use to add it to the typing but not expose it in the schema? Is there some other approach that I can use to pass it down into the field resolver?