feat(xor): support xoring more than two types (up to 200!) #27
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.
This approach leverages meta-programming, specifically the TypeScript Compiler API to generate the
XOR
type according to a new algorithm specified inxorFactory.js
. Here's the resultingXOR
type (205_708 chars ! 😅):This new algorithm allows us to extend the count of generic params that
XOR
accepts up to seemingly any arbitrary number (tentatively 200). Note that this new algorithm doesn't produce a recursive type. It instead produces a union, each member of which is designed to perform efficient "early bail-out" before performing the complex evaluation that corresponds to it, unless necessary (related param is defined). That's by design, since solutions involving recursive types have higher memory cost and quickly hit the TypeScript compiler's resolve stack limit (max 6 generic params during my testing). In contrast, the code describing a recursive type implementingXOR
is dramatically less and comes with much less processing overhead.Perhaps the next evolution could be a type that uses a recursive eval for up to 6 params (with early bail-out) and the "unfolded" solution that this PR brings when using more params.
The performance overhead of having (up to) 200 (10000% increase) possible generic type parameters was measured (roughly) to be only around +25% compared to the current implementation supporting 2 params. That's despite the type's immense definition size (>200KB of uglified TS code) and it processing two orders of magnitude more interdependent operands. Having 100 params brings the perf overhead only down to ~+18%. The community has hinted there might be need for high param counts for some users. Regardless, tuning the number of params supported is as easy as adjusting
xorParamCount
inxorFactory.js
💯. And given that bespoke DX, any user who needs much more than this count of params can easily clone the repo and generate their own larger-param-capacityXOR
type (just adjust the constant's value and runnpm run codegen
in your shell) and copy-paste it in their project.Note that this PR brings a non-breaking change by extending the existing API, which is important given the extensive userbase (>5M downloads) of
ts-xor
!Closes #22