facebook / facebook/relay

[relay-compiler] Unexpected type/__typename for fragments on interfaces

Open
#4,439 2 comments 6 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
19k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

Hello,

I have a case here where the typescript types generated by the relay-compiler look wrong to me.

Let's say I've got the following schema
```graphql
interface TestInterface implements Node{
id: ID!

fieldA: String!
}

type TypeWithFieldB implements Node & TestInterface {
id: ID!

fieldA: String!
fieldB: String!
}

type TypeWithFieldC implements Node & TestInterface {
id: ID!

fieldA: String!
fieldC: String!
}
```
# Example 1 (which works like I would expect it)
If I now create a fragment like this
```tsx
useFragment(graphql`fragment Test on TestInterface {
... on TypeWithFieldB {
__typename
fieldA
fieldB
}
... on TypeWithFieldC {
__typename
fieldA
fieldC
}

}`, null)
```
Then the generated types look good
```ts
export type Test$data = {
readonly __typename: "TypeWithFieldB";
readonly fieldA: string;
readonly fieldB: string;
readonly " $fragmentType": "Test";
} | {
readonly __typename: "TypeWithFieldC";
readonly fieldA: string;
readonly fieldC: string;
readonly " $fragmentType": "Test";
}
```
# Example 2 (Wrong __typename)
If I create a fragment like this (fieldA pulled to the top):
```tsx
useFragment(graphql`fragment Test2 on TestInterface {
fieldA

... on TypeWithFieldB {
__typename
fieldB
}
... on TypeWithFieldC {
__typename
fieldC
}

}`, null)
```
Then the generated types look like this:
```
export type Test2$data = {
readonly __typename: "TypeWithFieldB";
readonly fieldA: string;
readonly fieldB?: string;
readonly fieldC?: string;
readonly " $fragmentType": "Test2";
};
```
While the type itself looks like a sensible merge of TypeWithFieldB and TypeWithFieldC the __typename should probably not be "TypeWithFieldB".

# Example 3 (Wrong __typename caused by refetchable fragment)
```tsx
useRefetchableFragment(graphql`fragment Test3 on TestInterface @refetchable(queryName: "Test3RefetchQuery") {
... on TypeWithFieldB {
__typename
fieldA
fieldB
}
... on TypeWithFieldC {
__typename
fieldA
fieldC
}

}`, null)
```
Then the generated types look like in Example 2.
What is surprising to me here is that the fragment structure is chosen exactly as in the working example 1 with the only difference that here the fragment is marked as refetchable.

---
Repo with example code: https://github.com/joeried/relay-compiler-issue-repro/

If I'm not mistaken, then the generated types are just wrong, or am I mistaken? Is there a way to get types that are structured more like the ones in Example 1?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.