Skip to content
This repository was archived by the owner on Sep 27, 2023. It is now read-only.
This repository was archived by the owner on Sep 27, 2023. It is now read-only.

Adding __typename on a interface field generates generates string type instead of union type with constant strings #190

Open
@n1ru4l

Description

@n1ru4l

Schema Types:

type DiceRollCloseParenNode implements DiceRollDetail {
  content: String!
}

type DiceRollConstantNode implements DiceRollDetail {
  content: String!
}

interface DiceRollDetail {
  content: String!
}

type DiceRollDiceRollNode implements DiceRollDetail {
  content: String!
  min: Float!
  max: Float!
  rollResults: [DiceRollResult!]!
}

type DiceRollOpenParenNode implements DiceRollDetail {
  content: String!
}

type DiceRoll {
  result: Float!
  detail: [DiceRollDetail!]!
}
export const FormattedDiceRoll = createFragmentContainer(DiceRollRenderer, {
  diceRoll: graphql`
    fragment formattedDiceRoll_diceRoll on DiceRoll {
      result
      detail {
        __typename
        content
        ... on DiceRollDiceRollNode {
          content
          rollResults {
            dice
            result
            category
          }
        }
      }
    }
  `,
});

Generated Type:

export type formattedDiceRoll_diceRoll = {
    readonly result: number;
    readonly detail: ReadonlyArray<{
        readonly __typename: string;
        readonly content: string;
        readonly rollResults?: ReadonlyArray<{
            readonly dice: string;
            readonly result: number;
            readonly category: DiceRollCategory;
        }>;
    }>;
    readonly " $refType": "formattedDiceRoll_diceRoll";
};

Expected Generated Type:

export type formattedDiceRoll_diceRoll = {
    readonly result: number;
    readonly detail: ReadonlyArray<
      {
        readonly __typename: "DiceRollCloseParenNode" | "DiceRollOpenParenNode" | "DiceRollConstantNode";
        readonly content: string;
      } |
      {
        readonly __typename: "DiceRollDiceRollNode"
        readonly content: string;
        readonly rollResults: ReadonlyArray<{
            readonly dice: string;
            readonly result: number;
            readonly category: DiceRollCategory;
        }>;
      }
    }>;
    readonly " $refType": "formattedDiceRoll_diceRoll";
};

HOWEVER:

The following will generates the correct types:

Fragment Container:

export const FormattedDiceRoll = createFragmentContainer(DiceRollRenderer, {
  diceRoll: graphql`
    fragment formattedDiceRoll_diceRoll on DiceRoll {
      result
      detail {
        ... on DiceRollOperatorNode {
          __typename
          content
        }
        ... on DiceRollConstantNode {
          __typename
          content
        }
        ... on DiceRollOpenParenNode {
          __typename
          content
        }
        ... on DiceRollCloseParenNode {
          __typename
          content
        }
        ... on DiceRollDiceRollNode {
          __typename
          content
          rollResults {
            dice
            result
            category
          }
        }
      }
    }
  `,
});

Generated Code:

export type formattedDiceRoll_diceRoll = {
    readonly result: number;
    readonly detail: ReadonlyArray<{
        readonly __typename: "DiceRollOperatorNode";
        readonly content: string;
    } | {
        readonly __typename: "DiceRollConstantNode";
        readonly content: string;
    } | {
        readonly __typename: "DiceRollOpenParenNode";
        readonly content: string;
    } | {
        readonly __typename: "DiceRollCloseParenNode";
        readonly content: string;
    } | {
        readonly __typename: "DiceRollDiceRollNode";
        readonly content: string;
        readonly rollResults: ReadonlyArray<{
            readonly dice: string;
            readonly result: number;
            readonly category: DiceRollCategory;
        }>;
    } | {
        /*This will never be '%other', but we need some
        value in case none of the concrete values match.*/
        readonly __typename: "%other";
    }>;
    readonly " $refType": "formattedDiceRoll_diceRoll";
};

But this is how I expect union types to work. IMHO interface fields should not require that much boiler plate code.

GraphQL Codegen supports generating the "correct" interface selection set typings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions