Skip to content

Generated interface resolvers seem to be too narrowly typed #3538

Closed
@onethread

Description

@onethread

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

Metadata

Metadata

Assignees

Labels

pluginswaiting-for-releaseFixed/resolved, and waiting for the next stable release

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions