graphql / graphql/graphql-spec

Literal types support

Open
#878 37 comments 13 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
14.6k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

Consider adding literal types support to be able to express a union with more than a single discriminator:
```graphql
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](https://dev.to/babak/exhaustive-type-checking-with-typescript-4l3f).
Currently, the only partial alternative is to use enums:
```graphql
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:
```typescript
const WeaponFrame = ({weapon, children}: Props): JSX.Element => {
switch (weapon.type) {
case 'melee':
return {children};
case 'ranged':
return {children};
case 'magic':
return {children};
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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.