DeutschGitHub
partialpackages/better-set/src

Better Set

@ralphschuler/better-set

Demonstrates union, intersection and the existing directional difference contract.

Setset algebracollections

01 · Problem

What is it for?

Names such as difference become ambiguous unless the direction and mutation behavior are explicit.

02 · Mental model

How should you think about it?

Set membership defines the operation; a new set and a changed receiver are different contracts.

In this repository

Demonstrates union, intersection and the existing directional difference contract. except computes argument minus receiver. The direction is retained and regression-tested.

03 · Control flow

What happens in which order?

  1. Choose the left and right sets.
  2. Evaluate membership for each candidate.
  3. Add matching values to a new result.
  4. Mutate the receiver only for documented union operations.

04 · Building blocks

The important contracts

merge / both / except / filterPerform union, intersection, argument-minus-receiver difference and filtering.

05 · Build it yourself

Implement a small core

Start with this small independent implementation, then use the steps below to make its contract explicit.

  1. Choose the left and right sets.
  2. Evaluate membership for each candidate.
  3. Add matching values to a new result.
  4. Mutate the receiver only for documented union operations.
Concept sketch · may reference omitted helpers
class SetOps<T> extends Set<T> {
  union(other: Iterable<T>) {
    return new SetOps([...this, ...other]);
  }

  intersection(other: ReadonlySet<T>) {
    return new SetOps([...this].filter(value => other.has(value)));
  }

  difference(other: ReadonlySet<T>) {
    return new SetOps([...this].filter(value => !other.has(value)));
  }
}

06 · Verify

What should you test?

  • For A={1,2}, B={2,3}, assert A.except(B)={3}.
  • Check intersection, union and empty inputs.
  • Verify filtering does not mutate its source.

Try it yourself

Turn the first verification claim into a failing test, implement the smallest fix, then add a boundary case.

For A={1,2}, B={2,3}, assert A.except(B)={3}.

Compare your approach

Your check should fail when the stated invariant is deliberately broken, and pass again after the fix. Keep setup deterministic and assert an observable result.

07 · Limits

Trade-offs and failure modes

  • Object membership compares references.
  • except has an unusual direction retained for compatibility.
  • Result types differ between methods.
Important

except computes argument minus receiver. The direction is retained and regression-tested.

08 · Keep exploring

Source code and related ideas

yarn tsx packages/better-set/examples/basic.ts