dotansimha / dotansimha/graphql-code-generator
Generate discriminator-based polymorphism
- Dominant language
- TypeScript
- Stars
- 11.3k
- Forks
- 1.4k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 23
Description
### Is your feature request related to a problem? Please describe.
Typescript offers awesome field-based type-inference:
```ts
type Dog = {
species: Species.Dog;
masterName: string;
};
type Cat = {
species: Species.Cat;
slaveName: string;
};
type Animal = Dog | Cat;
const animal = {} as Animal;
if (animal.species === Species.Cat) {
console.log(`Hastily poor me some kibble, ${animal.slaveName}!`)
}
if (animal.species === Species.Dog) {
console.log(`Please, my Lord ${animal.masterName}, may I have some humble nourishment?`)
}
```
However when this model is translated to a graphql schema, the `Species.Cat` field in `Cat` is narrowed-down to `Species`.
Graphql on the server-side relies on a `resolveType` function. However, the schema itself does not contain such logic.
It is therefore not possible for `@graphql-codegen` to deduct back the discriminator-based polymorphism.
We end up with this:
```ts
type Dog = {
species: Species;
masterName: string;
};
type Cat = {
species: Species;
slaveName: string;
};
type Animal = Dog | Cat # Nice but kinda useless
```
Therefore we need somehow to compensate, by providing the logic, in order to restore the beautiful TS's polymorphism.
### Describe the solution you'd like
```ts
plugins: {
resolveType: {
Animal: {
discriminatorField: 'species',
possibleTypes: { /// Record
Cat: 'Cat',
Dog: 'Dog',
},
},
},
}
```
### Describe alternatives you've considered
#### Use typenames instead of a custom field.
This does work, however:
- Using `__typename` in the client-side and `species` in the server-side, is a bit clunky, I rather use the same discriminator.
- `__typename` field is a string, and I would rather use a proper typescript enum, which prevents more mistakes.
The package https://www.npmjs.com/package/@homebound/graphql-typescript-factories does generate a list of possible typenames for each interface. However the generated object is not `as const`ed, which makes unusable to generate a proper type.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.