Graphql-code-generator: Generated interface resolvers seem to be too narrowly typed

Created on 21 Feb 2020  Â·  2Comments  Â·  Source: dotansimha/graphql-code-generator

Describe the bug
It’s possible I’m using the generated resolver types incorrectly, but I’m following Apollo’s javascript example for resolving graphql interfaces, and I’d expect to able to do something similar, but in typescript with graphql-code-generator; i.e., a resolver for an interface type should be able to determine what concrete type of the interface should be returned.

E.g. in js:

const resolvers = {
  Book: {
    __resolveType(parent, context, info){
      if(parent.classes){
        return 'TextBook';
      }

      if(parent.colors){
        return 'ColoringBook';
      }

      return null;
    },
  },
  …
};

Unfortunately, the generated typescript resolver doesn’t allow me to check what possible types it can be. parent is typed to Book which has no information about subtypes. The typescript equivalent is below.

If there’s a different pattern I should be using, please let me know!

To Reproduce
Steps to reproduce the behavior:

  1. My GraphQL schema:
interface Book {
  title: String
}

type TextBook implements Book {
  title: String
  cost: Float
}

type ColoringBook implements Book {
  title: String
  colors: [String]
}

  1. My codegen.yml config file:
schema: "src/schema.graphql"
generates:
  src/types/server-graphql-types.ts:
    plugins:
      - typescript
      - typescript-resolvers:
        useIndexSignature: true
  1. Generated code:
export type ResolversParentTypes = {
  Query: {};
  Book: Book;
  TextBook: TextBook;
  ColoringBook: ColoringBook;
  …
};
export type BookResolvers<
  ContextType = any,
  ParentType extends ResolversParentTypes[“Book”] = ResolversParentTypes[“Book”]
> = {
  __resolveType: TypeResolveFn<
    "TextBook" | "ColoringBook",
    ParentType, // Because Resolvers uses the default BookResolver type, ParentType is `ResolversParentTypes[“Book”]`
    ContextType
  >;
  title?: Resolver<
    ResolversTypes[“String”],
    ParentType,
    ContextType
  >;
};

export type Resolvers<ContextType = any> = {
  Book?: BookResolvers;
}

Expected behavior

I would expect to be able to do this:

const bookResolver: BookResolvers = {
  __resolveType(parent, _context, _info) {
      if (parent.__typename === "TextBook")
        return "TextBook";
      else if (parent.__typename === "ColoringBook") {
        return "ColoringBook";
      }

      return null;
    }
}

But __typename doesn’t exist on parent. Since ParentType is typed to ResolversParentTypes[“Book”], the only available field will be title.

Environment:

  • apollo-server: 2.9.16
  • @graphql-codegen/...: 1.12.2
  • NodeJS: 12.9.1
bug plugins waiting-for-release

Most helpful comment

3618

All 2 comments

3618

Fixed in v1.13.1 🎉

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zenVentzi picture zenVentzi  Â·  3Comments

NickClark picture NickClark  Â·  3Comments

dotansimha picture dotansimha  Â·  3Comments

SimenB picture SimenB  Â·  3Comments

RIP21 picture RIP21  Â·  3Comments