dotansimha / dotansimha/graphql-code-generator

Generate discriminator-based polymorphism

Open
#9,135 0 comments 2 reactions 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.