fix(gql.tada): Fix recursive optional fragment types causing exponential complexity #319
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.
Summary
Patterns that require a
T | {}
optionality being merged into selections are causing exponential complexity. This is because all fields in a selection are merged using theobj
utility. However,T | {}
causes2^n
complexity in evaluating and flattening types in TypeScript.This is because for each
A & (B | {})
merge two variants are created,(A & B) | (A & {})
. For each subsequent addition (e.g.A & (B | {}) & (C | {})
) the complexity doubles ((A & B) | (A & C) | (A & B & C) | A
. This can quickly cause a recursion complexity error in TypeScript once we reach the limit of 16 variants.This fix addresses this by limiting the flattening of fields to just the fields and not optional sub-selections.
This fix however does have a few problems:
getPossibleTypeSelectionRec
just slightly too hard to follow for my tasteAs such, post-merge, we're not planning to release this fix as another stable release straightaway and are still looking for improvements.
Set of changes