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

Union type in an interface-only cannot be used #597

Open
svilen-ivanov-kubit opened this issue Oct 29, 2021 · 0 comments
Open

Union type in an interface-only cannot be used #597

svilen-ivanov-kubit opened this issue Oct 29, 2021 · 0 comments
Labels

Comments

@svilen-ivanov-kubit
Copy link

I'm unable to use an union in an interface unless that union is referenced in a concrete type.

Here is an example:

type Query {
    query: TestInterface
    # dummy: DummyType
}

interface TestInterface {
    testUnion: TestUnion
}

type TestInterfaceImpl implements TestInterface {
    testUnion: TestUnion1
    c: String
}

type DummyType {
    testUnion: TestUnion
}

type TestUnion1 {
    a: String
}

type TestUnion2 {
    b: String
}

union TestUnion = TestUnion1 | TestUnion2

TestInterface defines the testUnion field to be TestUnion. TestInterfaceImpl narrows down the field testUnion to TestUnion1.

Expected behavior

The schema should be parsed properly

Actual behavior

I get the following error:

Exception in thread "main" graphql.kickstart.tools.SchemaError: Expected type 'TestUnion' to be a GraphQLOutputType, but it wasn't!  Was a type only permitted for object types incorrectly used as an input type, or vice-versa?
	at graphql.kickstart.tools.SchemaParser.determineType(SchemaParser.kt:385)
	at graphql.kickstart.tools.SchemaParser.determineOutputType(SchemaParser.kt:368)
	at graphql.kickstart.tools.SchemaParser.createField(SchemaParser.kt:283)
	at graphql.kickstart.tools.SchemaParser.createInterfaceObject$lambda-32$lambda-31(SchemaParser.kt:233)
	at graphql.schema.GraphQLInterfaceType$Builder.field(GraphQLInterfaceType.java:318)
	at graphql.kickstart.tools.SchemaParser.createInterfaceObject(SchemaParser.kt:233)
	at graphql.kickstart.tools.SchemaParser.parseSchemaObjects(SchemaParser.kt:82)
	at graphql.kickstart.tools.SchemaParser.makeExecutableSchema(SchemaParser.kt:112)
	at Main.main(Main.kt:39)

The library reports that TestUnion is unused.

18:35:14.201 [main] WARN  g.kickstart.tools.SchemaClassScanner - Schema type was defined but can never be accessed, and can be safely deleted: DummyType
18:35:14.201 [main] WARN  g.kickstart.tools.SchemaClassScanner - Schema type was defined but can never be accessed, and can be safely deleted: TestUnion2
18:35:14.201 [main] WARN  g.kickstart.tools.SchemaClassScanner - Schema type was defined but can never be accessed, and can be safely deleted: TestUnion

If I simply reference the TestUnion in another query (uncomment line 3, dummy), the schema is parsed successfully.

Steps to reproduce the bug

Here minimal reproducible repository: https://github.com/svilen-ivanov-kubit/gql-union. Simply run ./gradlew run

Notes

I'm migrating my code from version 5 to version 12 and I used to define TestUnion to be an empty interface. This used pass with version 5 of the library but now it doesn't. It is invalid GraphQL according to the spec. Union type seems best according to the "Learn" section of the GQL site:

Union types are very similar to interfaces, but they don't get to specify any common fields between the types.

I was able to trace the issue to this change (fd28dbc, PR #83)

However, since my union is never a leaf (it is only referenced in interface) it is reported as unused and I get the error.

Let me know if the behaviour I'm expecting is correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant