Skip to main content

Immutable HashSet in TypeScript

class HashSet<T extends HashKey>

Immutable Hash Set

The HashSet<T> class stores numbers, strings, booleans, dates, or custom objects which implement the HashableObj and ComparableObj interface. HashSet implements the typescript-builtin ReadonlySet interface (which consists of the read-only methods of the JS builtin Set).

The HashSet is immutable, which means that no changes or mutations are allowed directly to the HashSet. Instead, modification operations such as HashSet.delete return a new HashSet which contains the result of the modification. The original HashSet is unchanged and can continue to be accessed and used. The HashSet implements this efficiently using structural sharing and does not require a full copy.

Creating Hash Sets

static empty<T extends HashKey>(): HashSet<T>
#Source

Static method to create a new empty HashSet

The item type must extend HashKey, which consists of strings, numbers, dates, booleans, or a custom user-defined object which implement the HashableObj and ComparableObj interfaces. These interfaces allows you to create complex keys which are made up of multiple properties.

While you can start with an empty HashSet and then use HashSet.add to add entries, it is more efficient to create the HashSet in bulk using either the static HashSet.from or HashSet.build or using various methods on LazySeq to convert a LazySeq to a HashSet.

static ofKeys<K extends HashKey, V>(map: HashMap<K, V>): HashSet<K>
#Source

Static method to produce a HashSet of the keys in a HashMap

Creates a HashSet consisting of all the keys in the given HashMap. This function is O(1) and very fast because the backing data structure is reused.

static from<T extends HashKey>(items: Iterable<T>): HashSet<T>
#Source

Efficiently create a new HashSet from a collection of items

static build<T extends HashKey, R>(
items: Iterable<R>,
key: (v: R) => T
): HashSet<T>
#Source

Efficiently create a new HashSet from a collection of items and a key extraction function

build efficiently creates a new HashSet by applying the given function to each item in the collection.

IReadOnlySet interface

𝑜𝑏𝑗.size: number
#Source

size is a readonly property containing the number of entries in the HashSet.

𝑜𝑏𝑗.has(t: T): boolean
#Source

Returns true if the item is in the HashSet

𝑜𝑏𝑗.[Symbol.iterator](): IterableIterator<T>
#Source

Iterates the items in the HashSet

This is the default iteration when using for .. of directly on the HashSet. It iterates all the items, but the order of iteration is an implementation detail and cannot be relied upon.

𝑜𝑏𝑗.entries(): IterableIterator<[T, T]>
#Source

Iterates the items in the HashSet

This provides an iterator to iterate all the items in the HashSet. Each item is iterated as a length-2 array with the item appearing twice. (This matches the builtin Set.entries method.) The order of iteration is an implementation detail and cannot be relied upon.

𝑜𝑏𝑗.keys(): IterableIterator<T>
#Source

Iterates the items in the HashSet

This provides an iterator to iterate all the items in the HashSet. The order of iteration is an implementation detail and cannot be relied upon. Both keys and values are equivalent for a HashSet.

𝑜𝑏𝑗.values(): IterableIterator<T>
#Source

Iterates the items in the HashSet

This provides an iterator to iterate all the items in the HashSet. The order of iteration is an implementation detail and cannot be relied upon. Both keys and values are equivalent for a HashSet.

𝑜𝑏𝑗.forEach(f: (val: T, val2: T, set: HashSet<T>) => void): void
#Source

Applys a function to each item in the HashSet

This applies the function f to each item in the hashmap. The item is provided twice (so as to match the builtin Set.forEach method). The order of iteration implementation detail and cannot be relied upon.

Iteration

𝑜𝑏𝑗.fold<R>(f: (acc: R, val: T) => R, zero: R): R
#Source

Reduce all the items in the HashSet to a single value

𝑜𝑏𝑗.toLazySeq(): LazySeq<T>
#Source

Creates a LazySeq which iterates all the items in the HashSet

Add and Delete

𝑜𝑏𝑗.add(t: T): HashSet<T>
#Source

Return a new HashSet with the given item added

If the item already exists, then the HashSet object instance is returned unchanged.

𝑜𝑏𝑗.delete(t: T): HashSet<T>
#Source

Return a new HashSet with the given item removed

If the item does not exist, then the HashSet object instance is returned unchanged.

Set Operations

𝑜𝑏𝑗.union(other: HashSet<T>): HashSet<T>
#Source

Returns a new HashSet which combines all entries in two HashSets

union produces a new HashSet which contains all the items in both HashSets. union guarantees that if the resulting HashSet is equal to this, then the HashSet object instance is returned unchanged.

static union<T extends HashKey>(...sets: readonly HashSet<T>[]): HashSet<T>
#Source

Create a new HashSet which combines all entries in a sequence of HashSets

HashSet.union is the static version of HashSet.union and allows unioning more than two HashSets at once. It produces a new HashSet which contains all the entries in all the HashSets. union guarantees that if the resulting HashSet is equal to the first non-empty HashSet in the sequence, then the HashSet object instance is returned unchanged.

𝑜𝑏𝑗.append(items: Iterable<T>): HashSet<T>
#Source

Return a new HashSet which adds the entries.

append is just a shorthand for a combination of HashSet.from and HashSet.union. union is very efficient at combining data structures, so the fastest way to bulk-add entries is to first create a data structure of the entries to add and then union them into the existing data structure. Thus, if you already have a HashSet, HashMap, or HashSet.build is more ergonomic, you should just directly use HashSet.union.

𝑜𝑏𝑗.intersection(other: HashSet<T>): HashSet<T>
#Source

Returns a new HashSet which contains only items which appear in both HashSets

intersection produces a new HashSet which contains all the items which appear in both HashSets. intersection guarantees that if the resulting HashSet is equal to this, then the HashSet object instance is returned unchanged.

static intersection<T extends HashKey>(
...sets: readonly HashSet<T>[]
): HashSet<T>
#Source

Returns a new HashSet which contains only items who appear in all HashSets

HashSet.intersection is a static version of HashSet.intersection, and produces a new HashSet which contains the items which appear in all specified HashSets. intersection guarantees that if the resulting HashSet is equal to the first HashSet, then the HashSet object instance is returned unchanged.

𝑜𝑏𝑗.difference(other: HashSet<T>): HashSet<T>
#Source

Returns a new HashSet which contains items which appear in this HashMap but NOT in the provided HashSet

difference produces a new HashSet which contains all the items which appear in this HashSet, except all the items from the other HashSet are removed. difference can be thought of as subtracting: this - other. difference guarantees that if the resulting HashSet is equal to this, then the HashSet object instance is returned unchanged.

𝑜𝑏𝑗.symmetricDifference(other: HashSet<T>): HashSet<T>
#Source

Returns a HashSet which contains only items which appear in exactly one of the two sets

symmetricDifference produces a new set which contains all the items appear in exactly one of this and other. If this or other are empty, the non-empty set is returned unchanged.

Transformation

𝑜𝑏𝑗.filter(f: (k: T) => boolean): HashSet<T>
#Source

Remove items from the HashSet that return false from a predicate

filter applies the function f to each item in the HashMap. If f returns false, the item is removed. filter guarantees that if no values are removed, then the HashSet object instance is returned unchanged.

𝑜𝑏𝑗.transform<U>(f: (s: HashSet<T>) => U): U
#Source

Apply a function to the HashSet

Applies the provided function f to this and returns the result. This is a convenience function which allows you to continue to chain operations without having to create a new temporary variable.

Set Operations

𝑜𝑏𝑗.isSubsetOf(largerSet: HashSet<T>): boolean
#Source

Returns true if each item of this exists in largerSet

isSubsetOf checks if this is a subset of largerSet, that is, if every item in this is also in largerSet.

𝑜𝑏𝑗.isSupersetOf(smallerSet: HashSet<T>): boolean
#Source

Returns true if each item of smallerSet exists in this

isSupersetOf checks if this is a superset of smallerSet, that is, if every item in smallerSet also exists in this.

𝑜𝑏𝑗.isDisjointFrom(other: HashSet<T>): boolean
#Source

Returns true if each item exists in exactly one of the two sets

isDisjointFrom checks if this is disjoint from other, that is, the intersection is empty.