I'm using apollo server with typescript and I'm having trouble getting the context parameter inside of my resolver to pick up that the name
property on context
is a string. Right now it's typed as any
and I'd like it to be typed as string
. I also see that the context
parameter is of type any, when I'd like it to be a specific interface. Is there anyway to tell context and it's properties what type I want it to be rather than them all being typed as any
?
const server = new ApolloServer({
typeDefs: gql`
type Query {
test: String
}
`,
resolvers: {
Query: {
test(parent: any, args: any, context, info: any) {
context.name // name is typed as "any" when I'd like it to be typed as "string"
}
}
},
context() {
return {
name: 'John Doe'
}
}
})
I tried to do something like this, but that's throwing an error.
context<{ name: string }>() {
return {
name: 'John Doe'
}
}
I did get it to work by explicitly telling context what it needs to be, but this way seems a bit tedious as I have to import Context
into every resolver file and cast manually.
interface Context {
name: string
}
const server = new ApolloServer({
...
resolvers: {
Query: {
test(parent: any, args: any, context: Context, info: any) {
context.name // name is typed as "string" here because I used "context: Context" explicitly
}
}
}
...
})
To enable introspection, set introspection: true in the options to ApolloServer 's constructor. You can also: Select Automatically redirect to Studio next time if you want to open Sandbox automatically whenever you visit localhost:4000. Open Sandbox directly at studio.apollographql.com/sandbox.
In GraphQL, a context is an object shared by all the resolvers of a specific execution. It's useful for keeping data such as authentication info, the current user, database connection, data sources and other things you need for running your business logic.
A resolver is a function that's responsible for populating the data for a single field in your schema. It can populate that data in any way you define, such as by fetching data from a back-end database or a third-party API.
If you're using graphql-code-generator to generate your types you can configure the context type in codegen.yml:
generates:
src/generated/graphql.ts:
config:
contextType: "src/types#Context"
Then define your context type:
export interface Context {
username: string;
}
Now the context
argument of your resolver methods will be typed Context
without having to import types or make any other changes.
By default the resolvers
field on the Config
object you're giving to ApolloServer
is open to any types, but you can use TypeScript to do your own type narrowing.
For reference, ApolloServer
accepts an instance of or array of IResolvers
objects as declared here: https://github.com/apollographql/apollo-server/blob/a241d34e9275bf6a23cf7aa3ddee57f90de7b364/packages/apollo-server-core/src/types.ts#L90. IResolvers
has generic type parameters, but those default to any: https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L298. In your code sample, Query
is one of the specific types that make up IResolvers
and test()
implements IFieldResolver
: https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L236.
You can take advantage of the fact that IResolvers
has generic parameters to restrict the type of the context
argument. For example, by explicitly specifying a type on the left side of an assignment, you can tell the compiler what to expect on the right:
interface Context {
username: string
}
const myResolvers: IResolvers<any, Context> = {
Query: {
test: (parent, args, context) => {
console.log(context.username) // based on generics TS knows context is supposed to be of type Context
}
}
}
new ApolloServer({
...
resolvers: myResolvers,
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With