Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(xor): support xoring more than two types (up to 200!) #27

Merged
merged 1 commit into from
Sep 16, 2023

Conversation

maninak
Copy link
Owner

@maninak maninak commented Sep 12, 2023

This approach leverages meta-programming, specifically the TypeScript Compiler API to generate the XOR type according to a new algorithm specified in xorFactory.js. Here's the resulting XOR type (205_708 chars ! 😅):

image

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 implementing XOR 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 in xorFactory.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-capacity XOR type (just adjust the constant's value and run npm 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

@maninak maninak self-assigned this Sep 12, 2023
@maninak maninak force-pushed the feat/22_multi-xor branch 6 times, most recently from 0caf007 to 16e7ec7 Compare September 13, 2023 16:58
@maninak maninak marked this pull request as ready for review September 13, 2023 16:58
@maninak maninak force-pushed the feat/22_multi-xor branch 3 times, most recently from 3d7ffa6 to abfb1d8 Compare September 16, 2023 20:44
@maninak maninak merged commit 27d3b9f into master Sep 16, 2023
@maninak maninak deleted the feat/22_multi-xor branch September 16, 2023 20:55
@maninak maninak restored the feat/22_multi-xor branch March 7, 2024 00:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Let XOR take multiple arguments?
1 participant