-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
The following is distilled down from a real-world example. In my app, I have Posts, which live inside a Group. I have a Linkable interface for types for which my app knows how to generate a URL. For a Group, we need to know the group type to put into the URL. For a Post, we need to know the Group it is in, as well as that Group type. A React component uses a fragment to fetch this data on anything that implements Linkable. When I create a Post, I want to link both to that Post and the Group that it's in, and so I spread my fragment on both.
Here's a very simplified version of my schema:
interface Linkable {
id: ID!
}
type Post implements Linkable {
id: ID!
group: Group!
}
type Group implements Linkable {
id: ID!
type: String!
}
type Query {
post: Post!
}
type Mutation {
createPost: Post!
}
Here's a mutation using @raw_response_type to create a post, including the two fragment spreads so I can link to both places:
graphql`
mutation TestMutation @raw_response_type {
createPost {
...TestLinkableFragment
group {
...TestLinkableFragment
}
}
}
`;
graphql`
fragment TestLinkableFragment on Linkable {
id
... on Post {
group {
id
type
}
}
... on Group {
type
}
}
`;
The raw type that Relay generates for this is:
export type TestMutation$rawResponse = {
readonly createPost: {
readonly __isLinkable: "Post";
readonly group: {
readonly __isLinkable: "Post";
readonly group: {
readonly id: string;
readonly type: string;
};
readonly id: string;
readonly type: string;
} | {
readonly __isLinkable: "Group";
readonly id: string;
readonly type: string;
} | {
readonly __isLinkable: "Group";
readonly id: string;
readonly type: string;
};
readonly id: string;
} | {
readonly __isLinkable: "Post";
readonly group: {
readonly __isLinkable: "Post";
readonly group: {
readonly id: string;
readonly type: string;
};
readonly id: string;
} | {
readonly __isLinkable: "Group";
readonly id: string;
} | {
readonly __isLinkable: "Group";
readonly id: string;
readonly type: string;
};
readonly id: string;
} | {
readonly __isLinkable: "Group";
readonly group: {
readonly __isLinkable: "Post";
readonly group: {
readonly id: string;
readonly type: string;
};
readonly id: string;
} | {
readonly __isLinkable: "Group";
readonly id: string;
} | {
readonly __isLinkable: "Group";
readonly id: string;
readonly type: string;
};
readonly id: string;
readonly type: string;
};
};
Note all of the places that types like this are generated:
{
readonly __isLinkable: "Group";
readonly id: string;
} | {
readonly __isLinkable: "Group";
readonly id: string;
readonly type: string;
}
When using the raw response type for an optimistic response (a common use-case), it's easy to forget to add the type, since TS will match the first arm of that!
It seems like a bug that two arms of a union would be generated with the same __isLinkable, since Relay tends to flatten these out in most other cases?
Honestly it would be even better if Relay could pick the correct arm of TestLinkableFragment, since we know that the type is a Group!.