# Typescript types for resolvers

**URL:** <https://community.apollographql.com/t/typescript-types-for-resolvers/5272>\
**Category:** Server\
**Tags:** server\
**Created:** [December 19, 2022, 1:21pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272 "2022-12-19T13:21:02Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Conny\_Gu](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/conny_gu/32/3568_2.png) [@Conny\_Gu](https://community.apollographql.com/u/Conny_Gu)\
**Post date:** [December 19, 2022, 1:21pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/1 "2022-12-19T13:21:02Z")

</div>

Hi all, how do you write the resolvers with typescript? I saw this example

```auto
const resolvers = {
  Query: {
    // Our resolvers can access the fields in contextValue
    // from their third argument
    currentUser: (parent, args, contextValue, info) => {
      return contextValue.dataSources.userApi.findUser(contextValue.token);
    },
  },
};

```

my question is: have the “parent”, “args”, “contextValue”, “info” types? In docs, there is nothing about it…But I think: “any” type will be a bad style…

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [December 19, 2022, 5:24pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/2 "2022-12-19T17:24:20Z")

</div>

Hey @Conny_Gu 👋!

`parent`, `args` and `contextValue` you’ll need to type yourself since they are dependent on your schema and your setup.

**`parent`**  
This value should be whatever you return from a parent resolver. For example, let’s say your schema looks something like this:

```graphql
query {
  currentUser: User
}

type User {
  firstName: String
}

```

And that you’re trying to resolve `User.firstName` in this query:

```graphql
query {
  currentUser {
    firstName
  }
}

```

In this case, the `parent` type should be equal to the TypeScript type returned from your `currentUser` resolver. Let’s call that TypeScript `User`. Your `parent` value would look something like this:

```typescript
import { User } from './types.ts' // or whenever you store this type

const resolvers = {
  User: {
    firstName: (parent: User) => {
      // ...
    }
  }
}

```

* * *

In your example above, since you’re trying to resolve a top-level `Query` field, the value is going to depend on whether you pass a [`rootValue`](https://www.apollographql.com/docs/apollo-server/api/apollo-server#rootvalue) option to your `ApolloServer` constructor. If you’ve passed a value to `rootValue`, then `parent` is going to be the same type as `rootValue`. If not, then `any` or `never` will likely suit you just fine since you’re likely not going to use that value.

**`args`**

This type will depend on your schema and whether the field you’re trying to resolve takes arguments or not. If your field takes no arguments, `any` or `never` should work just fine here. If you do, the object type should match the types in your schema. for example:

```graphql
# schema.graphql
type Query {
  posts(limit: Int!): [Post!]!
}

```

```typescript
interface QueryPostsArgs {
  limit: number
}

const resolvers = {
  Query: {
    posts: (parent: any, args: QueryPostsArgs) => {
      // ...
    }
  }
}

```

**`contextValue`**  
This type is going to depend on whether you pass a `context` function to the `ApolloServer` constructor. If you don’t pass `context`, then `any` or `never` is going to be ok here. If you do, the value should match what you return from that function. See the [“Sharing Context”](https://www.apollographql.com/docs/apollo-server/data/context) docs for an example of how you use context.

**`info`**  
You can type this with the `GraphQLResolveInfo` imported from the `graphql` package.

```typescript
import { GraphQLResolveInfo } from 'graphql';

```

* * *

Using your example above it will look something like this:

```typescript
import { GraphQLResolveInfo } from 'graphql';
import { RootValue, ContextValue } from './types'; // or wherever you store these types

interface QueryCurrentUserArgs {
  // empty for now since I don't know if your schema takes args here
}

const resolvers = {
  Query: {
    // Our resolvers can access the fields in contextValue
    // from their third argument
    currentUser: (
      parent: RootValue, 
      args: QueryCurrentUserArgs, 
      contextValue: ContextValue, 
      info: GraphQLResolveInfo
    ) => {
      return contextValue.dataSources.userApi.findUser(contextValue.token);
    },
  },
};

```

Hope that helps!

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [December 19, 2022, 9:50pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/3 "2022-12-19T21:50:35Z")

</div>

@Conny_Gu forgot to mention in my reply, you might also take a look at [GraphQL Code Generator](https://the-guild.dev/graphql/codegen), specifically the [TypeScript Resolvers Plugin’](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-resolvers). This can help automate the types for your resolvers. Check out our [docs](https://www.apollographql.com/docs/apollo-server/workflow/generate-types) on generating types to get some more info on this approach.

---

<div class="post-metadata">

**Author:** ![Conny\_Gu](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/conny_gu/32/3568_2.png) [@Conny\_Gu](https://community.apollographql.com/u/Conny_Gu)\
**Post date:** [December 20, 2022, 12:50pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/4 "2022-12-20T12:50:20Z")

</div>

Hi @jerelmiller thanks very much for the answer. Currently I am trying to use the codegen, but somehow it always show the type error. I don’t know, where to ask questions for codegen, maybe I will make here another post…

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [December 20, 2022, 5:13pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/5 "2022-12-20T17:13:41Z")

</div>

@Conny_Gu check out the [YouTube video](https://youtu.be/tHMaNmqPIC4) embedded on that typescript-resolvers page. It had some useful information on some of the advanced features. In it I discovered that the `mappers` property is which allows you to tweak the parent type sent into the resolver. Perhaps that might be of use? You should also be able to use the `contextType` option to ensure the default context type is the context type you use for your app. Try these two options and see if that helps!

---

<div class="post-metadata">

**Author:** ![Conny\_Gu](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/conny_gu/32/3568_2.png) [@Conny\_Gu](https://community.apollographql.com/u/Conny_Gu)\
**Post date:** [December 21, 2022, 3:04pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/6 "2022-12-21T15:04:28Z")

</div>

@jerelmiller thanks very much for the instruction. I watched the video and tried a night, still can not figure out the the error of resolvers.

So I made a small example:  
(I did this small example in a codesandbox: )

> **[CodeSandbox](https://codesandbox.io/p/github/blatoo/apollographql_codegen/draft/unruffled-chaplygin?file=%2Fsrc%2Fresolvers.ts&selection=%5B%7B%22endColumn%22%3A8%2C%22endLineNumber%22%3A8%2C%22startColumn%22%3A8%2C%22startLineNumber%22%3A8%7D%5D)**
>
> CodeSandbox is an online editor tailored for web applications.

lets say a job board website with two entities: Company and Job. A Company can have multiple jobs, and job can have only one Company. The models looks like:

```auto
export interface ICompany extends Entity {
  id: string
  name: string
  description: string
}

export interface IJob extends Entity {
  id: string
  companyId: string
  title: string
  description: string
}

```

but my schema.graphql looks like this:

```auto
type Company {
  id: ID!
  name: String!
  jobs: [Job!]
}

type Job {
  id: ID!
  title: String!
  company: Company!
}

type Query {
  company(id: ID!): Company
}

```

**Notice** : the main difference between the models and the Grapqhl Types are: The model `ICompany` doesn’t have **the “jobs” property** , but type `Company` do have jobs.

What I am doing is according the video, added the mappers in config:

```auto
schema: "./schema.graphql"
generates:
  ./src/ __generated__ /resolvers-types.ts:
    plugins:
      - "typescript"
      - "typescript-resolvers"
    config:
      useIndexSignature: true
      mappers:
        Company: ../db#ICompany
        Job: ../db#IJob

```

However, the generated type `Resolvers` is always wrong. I have no idea, whats happened.

```auto
export const resolvers: Resolvers = {
  Query: {
     company: (_root, { id }) => DB_Company.findById(id),
   },

  ...

```

Error is:  
Type ‘(\_root: {}, { id }: RequireFields\<QueryCompanyArgs, “id”\>) =\> Promise\<ICompany | undefined\>’ is not assignable to type ‘Resolver\<Maybe\<ResolverTypeWrapper\>, {}, any, RequireFields\<QueryCompanyArgs, “id”\>\> | undefined’.

However, if I change the `Resolver` to any, than everything works fine.

Can you have a check and point out, what’s the problem of the `Resolvers` type?

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [January 4, 2023, 7:23pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/7 "2023-01-04T19:23:47Z")

</div>

Thanks for the code snippet! This helps!

Looking at your CodeSandbox, I actually think you have this setup correctly, the problem is that there are cases where you expect a field to be non-nullable, but the return value of your resolver might return undefined. For example, this resolver:

```auto
Job: {
  company: (job) => {
    return DB_Company.findById(job.companyId)
  },
},

```

I’m seeing the following error:

```auto
Type '(job: IJob) => Promise<ICompany | undefined>' is not assignable to type 'Resolver<ResolverTypeWrapper<ICompany>, IJob, any, {}> | undefined'.
  Type '(job: IJob) => Promise<ICompany | undefined>' is not assignable to type 'ResolverFn<ResolverTypeWrapper<ICompany>, IJob, any, {}>'.
    Type 'Promise<ICompany | undefined>' is not assignable to type 'ResolverTypeWrapper<ICompany> | Promise<ResolverTypeWrapper<ICompany>>'.
      Type 'Promise<ICompany | undefined>' is not assignable to type 'Promise<ICompany>'.typescript(2322)

```

Pay close attention to the last line and this becomes apparent:

```auto
      Type 'Promise<ICompany | undefined>' is not assignable to type 'Promise<ICompany>'.typescript(2322)

```

This is the _return_ value that is incorrect from your resolver.

Here, your `DB_Company.findById(id)` might return `undefined`, but you’ve specified in your schema that its a non-null field. You can either make this a nullable field, or do something like this to fix the issue:

```auto
Job: {
  company: async (job) => {
    const company = await DB_Company.findById(job.companyId);
    
    if (!company) {
      throw new Error('Company not found');
    }
    
    return company;
  },
},

```

The error on `Query.company` is a bit more obscure. The issue here is that your resolver expect a return value of `Maybe<ResolversTypes['Company']>`, where `Maybe` is defined as `type Maybe<T> = T | null`. I see this particular resolver might return `undefined`, which is not compatible with `null`. You’ll either need to explicitly return null when the value is missing:

```auto
Query: {
    company: async (_root, { id }) => {
      const company = await DB_Company.findById(id);
      
      return company || null;
    }
  },

```

or you can update your codgen config to set the `maybeValue` to something that includes `undefined`:

```auto
# codgen.yml
generates:
  'path/to/file.ts':
     plugins: ['typescript']
     config:
       maybeValue: 'T | null | undefined'

```

I found both of these to clear up the type errors you’re seeing.

* * *

That `Resolver` type signature is a bit hard to read since it takes 4 generic values. The first 2 generic parameters are the ones that you care about the most. The first generic type is the return value of the resolver, and the second generic type is the parent type for the resolver (the type of the thing passed as the first argument to the resolver function).

Hope this helps!

---

<div class="post-metadata">

**Author:** ![Conny\_Gu](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/conny_gu/32/3568_2.png) [@Conny\_Gu](https://community.apollographql.com/u/Conny_Gu)\
**Post date:** [January 5, 2023, 12:40pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/8 "2023-01-05T12:40:34Z")

</div>

Hi @jerelmiller You are amazing!!! Thanks for the answer!!! I learned a lot from you!

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [January 5, 2023, 5:07pm UTC](https://community.apollographql.com/t/typescript-types-for-resolvers/5272/9 "2023-01-05T17:07:08Z")

</div>

You’re very welcome! Glad I could help!
