Why does @graphql-codegen/typescript declare the resolver parent type to be an output type?

Why does @graphql-codegen/typescript declare the resolver parent type to be an output type?


I am using @graphql-codegen/typescript to generate types for this graphql schema:

type Book {
  title: String
  author: String
  comment: String

type Query {
  books: [Book]

Excerpt from the generated code:

export type Book = {
  __typename?: 'Book';
  author?: Maybe<Scalars['String']['output']>;
  comment?: Maybe<Scalars['String']['output']>;
  title?: Maybe<Scalars['String']['output']>;

The TS type "Book" is the type used for the parent that gets passed to the resolvers for the fields of GQL type "Book".

I DO understand that the fields of GQL type "Book" are not marked as non-null, so a query might get null as a response value for any of them, and I also understand that any query may choose to omit a field from the response.

However, these things are irrelevant here because the TS type "Book" is not what gets passed in the response, but what gets passed to the field resolvers as the input. "Book" looks like it is an output type for the query, but is used as a resolver input type.

Therefore, I do not understand why the fields in Book are optional and typed as Maybe. Omitted fields don’t have their resolver called, and erroneous fields result from returning null or throwing an error in the resolver, both of which don’t even have a well-defined meaning for the input of the resolvers.

To further understand what gets passed around, I have implemented the resolvers for Book as follows:

const books = [
    title: 'The Awakening',
    author: 'Kate Chopin',
    title: 'City of Glass',
    author: 'Paul Auster',

const resolvers: Resolvers = {
  Query: {
    books: () => books,
  Book: {
    title: (book: Book) => {
      console.log("title", book);
      return book.title!;
    comment: (book: Book) => {
      console.log("comment", book);
      return "foobar";

So I am returning an object that has title and author, but no comment, from the parent resolver, then generate a comment on-the-fly in the "comment" resolver. I also log the parent object. The code gets run on Apollo Server.

Observation: The parent object that gets passed to the field resolvers is what I returned from the parent resolver, i.e. without a comment field and with both the title and author fields present, even when the actualy query does not ask for those fields.

It seems sensible to me that this "internal" object from the parent resolver gets passed to the field resolvers; it is just how I understand resolvers to work.

What is totally confusing, though, is that the code generator generates the type Book in the style of an "output" type, with all fields optional/Maybe and generated fields present, for that resolver input.

What am I missing?

Load 6 more related questions

Show fewer related questions


Leave a Reply

Your email address will not be published. Required fields are marked *