[relay-compiler] Incorrect typing of `__typename` in types generated by `@raw_query_response`
- Dominant language
- Rust
- Stars
- 19k
- Forks
- 1.9k
- PR merge metrics
- No merged PRs in 30d
Description
## What did you do?
I am using [msw](https://github.com/mswjs/msw) to mock the GraphQL request and return a dummy response. And to generate the correct dummy response, I am using `@raw_query_response` to generate the query response type.
```tsx
import {graphql} from "react-relay";
import {TestQuery$rawResponse} from './__generated__/TestQuery.graphql';
graphql`
query TestQuery($id: ID!) @raw_response_type {
node(id: $id) {
...TestQuery_node
}
}
`
graphql`
fragment TestQuery_node on Node {
id
__typename
... on Book {
title
}
... on Author {
name
}
}
`
// ok
const mockResponse1: TestQuery$rawResponse = {
node: {
__typename: 'Book',
__isNode: 'Book',
id: 'Book-1',
title: 'Yuyushiki',
},
}
// ok
const mockResponse2: TestQuery$rawResponse = {
node: {
__typename: 'Author',
__isNode: 'Author',
id: 'Author-1',
name: 'Bob',
},
}
```
## What actually happened?
If a field of `Book` type is missing, no type error occurs.
```ts
// This passes the type check.
const mockResponse3: TestQuery$rawResponse = {
node: {
__typename: 'Book',
__isNode: 'Book',
id: 'Book-1',
// title: 'Yuyushiki', // missing
},
}
```
## What did you expect to happen?
For `Book` type, `title` field should be required. Therefore, a type error should be reported.
## Additional Context
The problem seems to be caused by a loose type of `@raw_response_type` generated by relay-compiler. The actual response type generated by relay-compiler is shown below.
```ts
// src/__generated__/TestQuery.graphql.ts
// ...
export type TestQuery$rawResponse = {
readonly node: {
readonly __typename: "Author";
readonly __isNode: "Author";
readonly id: string;
readonly name: string;
} | {
readonly __typename: "Book";
readonly __isNode: "Book";
readonly id: string;
readonly title: string;
} | {
readonly __typename: string;
readonly __isNode: string;
readonly id: string;
};
};
// ...
```
The last `{ readonly __typename: string; readonly __isNode: string; readonly id: string; }` is important. The type of `mockResponse3` matches this, so it passes the type check.
I think the relay-compiler should generate a response type that is strictly `__typename` typed, as follows:
```ts
// src/__generated__/TestQuery.graphql.ts
// ...
// The union types that accept the names of all GraphQL types
type TypeName = "Author" | "Book" | "Image";
export type TestQuery$rawResponse = {
readonly node: {
readonly __typename: "Author";
readonly __isNode: "Author";
readonly id: string;
readonly name: string;
} | {
readonly __typename: "Book";
readonly __isNode: "Book";
readonly id: string;
readonly title: string;
} | {
readonly __typename: Exclude;
readonly __isNode: Exclude;
readonly id: string;
};
};
// ...
```
## Link to Minimal Reproducible Example
- https://github.com/mizdra/relay-compiler-issue-repro
Contributor guide
Assessment
This issue has not been assessed yet.