I have a simple Apollo GraphQL subgraph where I want to set the type for my context arg in my resolvers.
I create a resolver and set the type for context as follows:
interface Context {
dataSources: {
shopify: Shopify;
}
}
const server = new ApolloServer({
schema: buildSubgraphSchema({
typeDefs,
resolvers: {
Query: {
shop(_, _args, ctx: Context) {
console.log("ctx:", ctx)
},
}
}
}),
dataSources: () => ({
shopify: new Shopify()
})
});
However, it appears the Context
interface I am setting is incompatible with the type my resolver expects and I get the following error:
Argument of type '{ typeDefs: any; resolvers: { Query: { shop(_: any, _args: any, ctx: Context): void; }; }; }' is not assignable to parameter of type 'DocumentNode | (GraphQLSchemaModule | DocumentNode)[] | LegacySchemaModule'.
Types of property 'resolvers' are incompatible.
Property 'Query' is incompatible with index signature.
Type '{ shop(_: any, _args: any, ctx: Context): void; }' is not assignable to type 'GraphQLScalarType<unknown, unknown> | { [enumValue: string]: string | number; } | { [fieldName: string]: GraphQLFieldResolver<any, unknown, any, unknown> | { requires?: string | undefined; resolve: GraphQLFieldResolver<...>; }; }'.
Types of property 'shop' are incompatible.
Type '(_: any, _args: any, ctx: Context) => void' is not assignable to type 'string | number | GraphQLFieldResolver<any, unknown, any, unknown> | { requires?: string | undefined; resolve: GraphQLFieldResolver<any, unknown, any, unknown>; } | undefined'.
Type '(_: any, _args: any, ctx: Context) => void' is not assignable to type 'GraphQLFieldResolver<any, unknown, any, unknown>'.
Types of parameters 'ctx' and 'context' are incompatible.
Type 'unknown' is not assignable to type 'Context'.ts(2345)
How can I set the context type for my resolver so I can get access to the interface and datasources etc?
2
Answers
The
ApolloServer
class is generic, you should specify your custom context as a type parameter. See the docs and these unit tests.OK I think I found a better solution.
First things first lets really understand what
buildSubgraphSchema
can accept:The problem is we are trying to pass in a
LegacySchemaModule
({typeDefs, resolvers}
) but due to the<unknown>
generic being passed in to theGraphQLResovlerMap
creates a conflict with an explicitly definedContext
What we need to use in to actually act on context within the resolver is a
GraphQLSchemaModule
defined as follows:So with a resolver defined like this:
We can now pass in an array of
(GraphQLSchemaModule | DocumentNode)[]
:That worked for me, no ts errors and the server started up great. Open to suggestions though from the community as to better patterns here.
Ultimately I think codegen tools are designed to solve alot of these problems. I’m diving into this now: https://the-guild.dev/graphql/codegen
Have fun!