
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
recursive-set
Advanced tools
Mutable recursive sets with ZFC axioms for TypeScript. High-Performance Array Backend.
High-performance collection library for TypeScript supporting value semantics (deep equality) and recursive structures. Version 8 introduces a new hash-based architecture optimized for high-throughput workloads like SAT solvers and graph algorithms.
RecursiveSet provides mathematical sets and maps where equality is determined by structure/content rather than object reference (e.g., {1, 2} is equal to {2, 1}).
Key Architectural Features:
npm install recursive-set
Sets automatically deduplicate elements based on their value or structure.
import { RecursiveSet } from "recursive-set";
// Primitive values
const numbers = new RecursiveSet(1, 2, 3);
numbers.add(1); // No effect, 1 is already present
// Recursive structures (Sets of Sets)
const setA = new RecursiveSet(1, 2);
const setB = new RecursiveSet(2, 1);
const metaSet = new RecursiveSet<RecursiveSet<number>>();
metaSet.add(setA);
metaSet.add(setB);
console.log(metaSet.size); // 1, because setA equals setB
RecursiveMap allows using complex objects (like Tuples or Sets) as keys.
import { RecursiveMap, Tuple } from "recursive-set";
const transitions = new RecursiveMap<Tuple<[string, string]>, number>();
const edge = new Tuple("q0", "q1");
transitions.set(edge, 1);
// Retrieval using a new, structurally identical key
console.log(transitions.get(new Tuple("q0", "q1"))); // 1
To guarantee hash stability, collections become immutable (frozen) once their hash code is computed or they are inserted into another collection.
const A = new RecursiveSet(1);
const B = new RecursiveSet(A); // Accessing A's hash to store it in B freezes A.
try {
A.add(2); // Throws Error: Frozen Set modified.
} catch (e) {
// Expected behavior
}
// Use mutableCopy to continue editing
const C = A.mutableCopy();
C.add(2);
This library optimizes for raw speed and assumes strict adherence to the following contracts. Violating them leads to undefined behavior.
NaN and Infinity are strictly forbidden. They break strict equality checks and integer optimization paths.{}) are not supported. Keys must implement the Structural interface (provide equals, hashCode, and toString).hashCode (e.g., 42) forces all elements into a single bucket, degrading performance to $O(N)$.toString() implementations must utilize compareVisualLogic for nested structures. Failing to do so results in unstable string output.hashCode must not change.RecursiveSet cannot contain itself, directly or indirectly. Runtime checks are omitted for performance; creating a cycle will cause a Stack Overflow during hashing.type Primitive = number | string;
type Value = Primitive | Structural;
interface Structural {
readonly hashCode: number;
equals(other: unknown): boolean;
toString(): string;
}
new RecursiveSet<T>(...elements: T[]): Creates a set from the given arguments.add(element: T): void: Adds an element ($O(1)$ amortized).remove(element: T): void: Removes an element ($O(1)$ amortized).Added in v8.2.0 — These methods iterate directly over internal storage, avoiding the memory overhead of spreading into a temporary Array ([...set]).
map<U>(fn: (v: T) => U): RecursiveSet<U>
filter(fn: (v: T) => boolean): RecursiveSet<T>
filterMap<U>(predicate: (v: T) => boolean, mapper: (v: T) => U): RecursiveSet<U>
{ f(x) : x in M | p(x) } in a single pass..filter(...).map(...) as it avoids creating an intermediate set.reduce<U>(fn: (acc: U, v: T) => U, init: U): U
every(fn: (v: T) => boolean): boolean
false immediately upon the first mismatch ($O(1)$ best case).some(fn: (v: T) => boolean): boolean
true immediately upon the first match ($O(1)$ best case).// Example: High-Performance Check
const largeSet = new RecursiveSet(0, 1, 2, ...);
// Instead of: largeSet.filter(x => x % 2 === 0).map(x => x * x) <-- Creates intermediate Set
// Use: largeSet.filterMap(x => x % 2 === 0, x => x * x) <-- Single pass, zero overhead
All operations return a new RecursiveSet instance.
union(other): RecursiveSet<T>intersection(other): RecursiveSet<T>difference(other): RecursiveSet<T> ($A \setminus B$)symmetricDifference(other): RecursiveSet<T>cartesianProduct<U>(other): RecursiveSet<Tuple<[T, U]>>powerset(): RecursiveSet<RecursiveSet<T>> (Throws if size > 20)has(element: T): booleanequals(other: unknown): booleanisSubset(other): booleanisSuperset(other): booleanmutableCopy(): RecursiveSet<T>: Returns a shallow mutable clone.size: numberhashCode: number: Computes hash and freezes the set.A hash map supporting Value keys.
set(key: K, value: V): voidget(key: K): V | undefineddelete(key: K): booleanhas(key: K): booleanmutableCopy(): RecursiveMap<K, V>An immutable, hashable sequence of values. Useful for composite keys.
new Tuple(...elements: T[])get(index: number): T[index]length: numberThis library was developed as a student research project under the supervision of Karl Stroetmann.
Special thanks for his architectural guidance on homogeneous sets and the theoretical foundations required for high-performance set engines.
git clone [https://github.com/cstrerath/recursive-set.git](https://github.com/cstrerath/recursive-set.git)
npm install
npm run build
npx tsx test/test.ts
npx tsx test/nqueens.ts
MIT License © 2025 Christian Strerath. See LICENSE.
FAQs
Mutable recursive sets with ZFC axioms for TypeScript. High-Performance Array Backend.
We found that recursive-set demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.