Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interface implementations are missing #726

Closed
HitkoDev opened this issue Oct 14, 2020 · 1 comment · Fixed by #736
Closed

Interface implementations are missing #726

HitkoDev opened this issue Oct 14, 2020 · 1 comment · Fixed by #736
Assignees
Labels
Bug 🐛 Something isn't working Community 👨‍👧 Something initiated by a community Solved ✔️ The issue has been solved
Milestone

Comments

@HitkoDev
Copy link

HitkoDev commented Oct 14, 2020

Describe the Bug
Interface implementations are stripped by

if (!this.usedInterfaceTypes.has(interfaceClass)) {
return false;
}

unless interface is directly used in @Mutation or @Query decorators.

To Reproduce

import { printSchema } from "graphql";
import "reflect-metadata";
import { buildSchema, Field, InterfaceType, ObjectType, Query, Resolver } from "type-graphql";

@InterfaceType()
export class IFace {
    @Field(() => String)
    val: string;
}

@ObjectType({ implements: IFace })
export class Foo extends IFace {
    constructor() {
        super();
        this.val = "Foo";
    }
}

@ObjectType({ implements: IFace })
export class Bar extends IFace {
    constructor() {
        super();
        this.val = "Bar";
    }
}

@ObjectType()
export class FooBar {
    @Field(() => IFace)
    iface: IFace;

    constructor() {
        this.iface = Math.random() > 0.5
            ? new Foo()
            : new Bar();
    }
}

@Resolver()
export class QueryResolver {
    // Doesn't include Foo & Bar
    @Query(() => FooBar)
    foobar() {
        return new FooBar();
    }

    // Properly includes Foo & Bar
    /* @Query(() => IFace)
    iface() {
        return Math.random() > 0.5
            ? new Foo()
            : new Bar();
    }*/
}

buildSchema({
    resolvers: [
        QueryResolver,
    ],
})
    .then(schema => console.log(printSchema(schema)))
    .catch(console.error);

Actual Behavior
Generated schema looks like

type Query {
  foobar: FooBar!
}

type FooBar {
  iface: IFace!
}

interface IFace {
  val: String!
}

Expected Behavior
Generated schema looks like

type Foo implements IFace {
  val: String!
}

interface IFace {
  val: String!
}

type Bar implements IFace {
  val: String!
}

type Query {
  foobar: FooBar!
}

type FooBar {
  iface: IFace!
}

Logs
Runtime Object type "Foo" is not a possible type for "IFace".

Environment (please complete the following information):

  • OS: all
  • Node: all
  • Package version: since 1.0.0
  • TypeScript version: all

Additional Context
It apereas that usedInterfaceTypes in schema-generator.ts is only properly populated after all field thunks are resolved, which doesn't happen until after we call new GraphQLSchema in

const schema = new GraphQLSchema({

@MichalLytek
Copy link
Owner

The docs says:

By default, if the interface type is explicitly used in schema definition (used as a return type of a query/mutation or as some field type), all object types that implement that interface will be emitted in schema, so we don't need to do anything.

So it looks like a bug, I'll have to cover your case by tests.
In the meantime you can use orphanedTypes as a workaround for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug 🐛 Something isn't working Community 👨‍👧 Something initiated by a community Solved ✔️ The issue has been solved
Projects
None yet
2 participants