Apollo-server: Typescript errors for context object in Apollo gateway

Created on 18 Sep 2019  ·  6Comments  ·  Source: apollographql/apollo-server

Package Versions:
@apollo-gateway: 0.10.4

Using the code below (from: [https://www.apollographql.com/docs/apollo-server/federation/implementing/]) I wouldn't expect to see any errors when using typescript.

const gateway = new ApolloGateway({
  serviceList: [
    { name: 'products', url: 'http://localhost:4001' },
    // other services
  ],
  buildService({ name, url }) {
    return new RemoteGraphQLDataSource({
      url,
      willSendRequest({ request, context }) {
        // pass the user's id from the context to underlying services
        // as a header called `user-id`
        request.http.headers.set('user-id', context.userId);
      },
    });
  },
});

However, typescript warns me that "Property 'userId' does not exist on type 'TContext'."

Looking at the underlying code it appears that willSendRequest should accept any key value pair with a string but that doesn't appear to be the case. Although Im not sure where the error could be.

Sorry if I have missed anything, Im still learning some of the advanced methods in typescript.

👩‍🚀 federation

Most helpful comment

Adding to this issue, if a type of { request: GraphQLRequest, context: Context } is added, TypeScript will complain that the provided Context isn't compatible with TContext.

All 6 comments

I have the same issue, and also when using the example with willSendResponse listed in https://www.apollographql.com/docs/apollo-server/federation/implementing/#customizing-outgoing-responses.

For now I cast context to any when accessing any non-standard fields.

Adding to this issue, if a type of { request: GraphQLRequest, context: Context } is added, TypeScript will complain that the provided Context isn't compatible with TContext.

Any update on this? I'm also having trouble adding types to willSendRequest.

It looks the author misunderstands the way to use generic type in the class. It should pass generic type from class to it's method, but in code it only set generic type on the method.

The correct one would be:

export class RemoteGraphQLDataSource<TContext> implements GraphQLDataSource { // <- pass generic from class
  public willSendRequest?<TContext>( // <- so we could pass our own context type here
    requestContext: Pick<
      GraphQLRequestContext<TContext>,
      'request' | 'context'
    >,
  ): ValueOrPromise<void>;
}

I can make a PR later.

I ran into this issue today trying to clean up some of my gateway code. I've fixed the Typescript generics typing in PR #3865. In the meantime, there is a workaround I've been using in my gateway currently:

import { ApolloGateway, RemoteGraphQLDataSource } from "@apollo/gateway";
import { GraphQLRequest } from "apollo-server-core";

interface IContext {
  user?: {
    id: string;
  };
}

const gateway = new ApolloGateway({
  buildService({ url }) {
    return new RemoveGraphQLDataSource<IContext>({
      url,
      willSendRequest({ request, context }: { request: GraphQLRequest, context: IContext }) {
        // "context" will now be typed to IContext
      }
    });
  }
});

Should be fixed by #3865. Please report back if this isn't the case!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danilobuerger picture danilobuerger  ·  3Comments

dobesv picture dobesv  ·  3Comments

manuelfink picture manuelfink  ·  3Comments

jpcbarros picture jpcbarros  ·  3Comments

hiucimon picture hiucimon  ·  3Comments