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

[relay-compiler] Incorrect typing of __typename in types generated by @raw_query_response #4442

Open
mizdra opened this issue Sep 7, 2023 · 2 comments

Comments

@mizdra
Copy link

mizdra commented Sep 7, 2023

What did you do?

I am using 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.

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.

// 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.

// 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:

// 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<TypeName, "Author" | "Book">;
    readonly __isNode: Exclude<TypeName, "Author" | "Book">;
    readonly id: string;
  };
};
// ...

Link to Minimal Reproducible Example

@mizdra
Copy link
Author

mizdra commented Sep 7, 2023

If this proposal is acceptable, I am going to create a Pull Request. Is this proposal acceptable?

@mizdra
Copy link
Author

mizdra commented Jan 23, 2024

I would like to know the opinion of the maintainer as to whether this proposal is acceptable. We are experiencing many runtime errors due to this issue in our project. Therefore, we are looking forward to this proposal.

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

No branches or pull requests

1 participant