Repository navigation
Preserve discriminated unions when merging query relations - #156
Merged
Merged
Conversation
## How the merge works For each possible item type, replace any fields supplied by the relations: ```ts type MergeRelated<TItem, TRelated extends object> = TItem extends unknown ? Omit<TItem, keyof TRelated> & TRelated : never; ``` - `keyof TRelated` gives the relation field names. - `Omit<TItem, keyof TRelated>` removes those fields from the original item. - `& TRelated` adds the relation fields with their new types. The subtle part is `TItem extends unknown`. Every type matches `unknown`, but TypeScript has a special rule: this conditional processes **each union member separately**. For example: ```ts StringField | DateField | ReferenceField; ``` becomes effectively: ```ts MergeStringField | MergeDateField | MergeReferenceField; ``` Each variant keeps its own properties and discriminator. Without the conditional, `Omit` processes the union as a whole and loses those relationships. The `never` branch is the required "otherwise" part of the conditional; ordinary item types always take the first branch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


How the merge works
For each possible item type, replace any fields supplied by the relations:
keyof TRelatedgives the relation field names.Omit<TItem, keyof TRelated>removes those fields from the original item.& TRelatedadds the relation fields with their new types.The subtle part is
TItem extends unknown. Every type matchesunknown, but TypeScript has a special rule: this conditional processes each union member separately.For example:
becomes effectively:
Each variant keeps its own properties and discriminator. Without the conditional,
Omitprocesses the union as a whole and loses those relationships.The
neverbranch is the required "otherwise" part of the conditional; ordinary item types always take the first branch.