How to properly pass Id down to field resolver without having it explicitly typed

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?