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