Sorry the title is a bit of a mouthful. :)
Describe the bug
When generating types for a query for an interface, the __typename field is set to just the interface name, which means you can't switch on its implementors. This only happens when the subtypes are in named fragments, it works fine with inline fragments.
To Reproduce
Schema:
type Query {
task: Task
}
interface Task {
id: ID!
}
type A implements Task {
id: ID!
a: String
}
type B implements Task {
id: ID!
b: String
}
Query:
query {
task {
id
__typename
...AFrag
...BFrag
}
}
fragment AFrag on Task {
... on A {
a
}
}
fragment BFrag on Task {
... on B {
b
}
}
Generated types (line 18):

Note: I would've copied the generated code in here, but the playground on your site doesn't allow copy and paste :(
Expected behavior
I expect __typename on Task to be "A" | "B".
Environment:
Additional context
Compare the above behaviour to the behaviour of inline fragments...
Schema:
type Query {
task: Task
}
interface Task {
id: ID!
}
type A implements Task {
id: ID!
a: String
}
type B implements Task {
id: ID!
b: String
}
Query:
query {
task {
id
__typename
...AFrag
...BFrag
}
}
Generated types:

And you can see the __typename of Task is correctly the union of the fragment's __typename.
Hi.
I have the same issue.
But imo the __typename is more difficult than that.
In my case, backend developpers added a new Task implementation.
type C implements Task {
id: ID!
c: String
}
But all the implementation that was done in the front were
if (obj.__typename === 'A') {
// Do something for type A
} else {
// Do something for type B
}
which is actually a mistake because now all type C goes into the else.
IMO, the __typename in these kind of case should be 'Task' | 'A' | 'B' which is the safest way, you can add as much implementation as you want and the front code is still going to be correct. 'Task' is here representing all the futur implementation that you can get.
Hope I'm clear.
Regards
Fixed in the recent refactor. we now override __typename and we are using brackets with | when fragments for different types are used, it also means that you can get better fragments matching and the correct __typename.
Fix available in 1.0.0 馃憤
Most helpful comment
Hi.
I have the same issue.
But imo the __typename is more difficult than that.
In my case, backend developpers added a new Task implementation.
But all the implementation that was done in the front were
which is actually a mistake because now all type C goes into the else.
IMO, the __typename in these kind of case should be
'Task' | 'A' | 'B'which is the safest way, you can add as much implementation as you want and the front code is still going to be correct. 'Task' is here representing all the futur implementation that you can get.Hope I'm clear.
Regards