Skip to content

Literal types support #878

Open
Open
@PinkaminaDianePie

Description

@PinkaminaDianePie

Consider adding literal types support to be able to express a union with more than a single discriminator:

type Sword {
  weaponType: "melee"!
  aptitude: "neutral"!
  damage: Float!
}

type Rifle {
  weaponType: "ranged"!
  aptitude: "technological"!
  damage: Float!
}

type Spellbook {
  weaponType: "magic"!
  aptitude: "magical"!
  damage: Float!
  chargesLeft: Int!
}

union Weapon = Sword | Rifle | Spellbook

__typename is useless in a case where multiple discriminators are needed. Multiple discriminators allow us to write more type-safe code, using exhaustive type check.
Currently, the only partial alternative is to use enums:

enum WeaponType {
  melee
  ranged
  magic
}

enum ItemAptitude {
  neutral
  technological
  magical
}

type Sword {
  weaponType: WeaponType!
  aptitude: ItemAptitude!
  damage: Float!
}

type Rifle {
  weaponType: WeaponType!
  aptitude: ItemAptitude!
  damage: Float!
}

type Spellbook {
  weaponType: WeaponType!
  aptitude: ItemAptitude!
  damage: Float!
  chargesLeft: Int!
}

union Weapon = Sword | Rifle | Spellbook

The problem is that it doesn't allow to use of different properties as union discriminators. Consider such a react component:

const WeaponFrame = ({weapon, children}: Props): JSX.Element => {
  switch (weapon.type) {
    case 'melee':
      return <MeleeWeaponFrame>{children}</MeleeWeaponFrame>;
    case 'ranged':
      return <RangedWeaponFrame ammo={player.ammo}>{children}</RangedWeaponFrame>;
    case 'magic':
      return <MagicWeaponFrame charges={weapon.chargesLeft}>{children}</MagicWeaponFrame>;
    default:
      ((_: never) => _)(weapon.type);
      throw new Error('unreachable case');
  }
}

here I know that if type of weapon is magical, I need to display chargesLeft property. however, it's impossible to represent it in graphql, so it's also impossible to generate a typescript type from a schema.

The only solutions left is to give up on type safety and hope that every developer won't forget to check every case, or just give up on generating types from the graphql schema and instead write all of them manually, casting graphql query results to manual typings on API level. Any of these solutions have multiple points of failure, so there is no easy and safe way to represent such kind of data at this moment.

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