Class-based API for Immutable TypeScript Collections
This module is the main import of immutable-collections and implements the class-based API. This API consists of the HashMap, HashSet, OrderedMap, OrderedSet, and LazySeq classes (along with some utility functions).
import { HashMap } from "@seedtactics/immutable-collections";
const h = HashMap.from([ [1, "Hello"], [2, "World"] ]);
console.log(h.get(1)); // prints Hello
console.log(h.get(2)); // prints World
const h2 = h.set(1, "Goodbye");
console.log(h2.get(1)); // prints Goodbye
console.log(h.get(1)); // prints Hello
Immutable Hash Map
The HashMap<K, V>
class stores key-value pairs where the keys have type K
and the values type V
. Keys can be numbers, strings, booleans, dates, or
custom objects which implement the HashableObj and ComparableObj interfaces.
HashMap
implements the typescript-builtin ReadonlyMap
interface (which
consists of the read-only methods of the JS builtin
Map).
See full class details for HashMap
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).
See full class details for HashSet
Immutable Ordered Map
The OrderedMap<K, V>
class stores key-value pairs where the keys have type K
and the values type V
.
Keys can be numbers, strings, booleans, dates, or custom objects which implement the ComparableObj interface.
The entries are stored in a balanced binary tree, and various methods can iterate over the entries in either ascending
or descending order of keys. OrderedMap implements the typescript-builtin ReadonlyMap
interface (which
consists of the read-only methods of the JS builtin Map).
See full class details for OrderedMap
Immutable Ordered Set
The OrderedSet<T>
class stores numbers, strings, booleans, dates, or custom objects which implement the
ComparableObj interface. OrderedSet implements the typescript-builtin ReadonlySet
interface (which consists of the read-only methods of
the JS builtin Set).
See full class details for OrderedSet
A class-wrapper around iterables
The LazySeq<T>
class stores an iterable
of type T
and provides a number of methods to transform the iterable.
The general format for data manipulation is to start with some data in
a data structure such as an array, object, HashMap, etc. Create a new
LazySeq chain starting from the initial data, call various transformation
methods to map, group, filter, aggregate the data, and finally terminate the
chain by converting back to a data structure. Because most of the transformation
methods are lazy, the new terminating data structure can be built directly from the
transformed data in one pass.
See full class details for LazySeq
Comparison Utils
The possible types for a key in an OrderedMap
Interface allowing custom key objects in an OrderedMap
If you wish to use a custom object as a key in a HashMap or OrderedMap, you must implement the compare
function.
The compare
function should return a negative number if this < other
, return zero if this
equals other
, and
return a positive number if this > other
. A common technique is to use subtraction to compare numbers
and String.localeCompare
to compare srings. Comparing multiple properties can either use a sequence of if
statements or use ||
to combine.
Example
class SomeKey {
public readonly a: number;
public readonly b: string;
constructor(a: number, b: string) {
this.a = a;
this.b = b;
}
compare(other: SomeKey): number {
return (this.a - other.a) || this.b.localeCompare(other.b);
}
}
function mkCompareByProperties<T>(
...getKeys: ReadonlyArray<ToComparable<T>>
): (a: T, b: T) => -1 | 0 | 1
Combine multiple comparable properties into a single comparison function
mkCompareByProperties
will return a comparison function for the type T
which
compares multiple properties in order. Each property is specified by an
extraction function which extracts the property from the type T
. The comparison
function will compare each property in order, returning as soon as a single property is
not equal. Strings are compared using
localeCompare.
This function can optionally be used to implement ComparableObj, but typically
a direct implementation is shorter. mkCompareByProperties
is instead used primarily
by LazySeq.
Example
type Foo = {
readonly someNum: number;
readonly someStr: string;
}
const compareFoo: (a: Foo, b: Foo) => -1 | 0 | 1 = mkCompareByProperties(
f => f.someNum,
{ desc: f => f.someStr }
);
console.log(compareFoo(
{ someNum: 1, someStr: "Hello"},
{ someNum: 2, someStr: "Hello"}
)); // prints -1
console.log(compareFoo(
{ someNum: 42, someStr: "AAA"},
{ someNum: 42, someStr: "ZZZ"}
)); // prints 1 due to descending ordering of the strings
export type ToComparableBase<T> =
| ((t: T) => number | null)
| ((t: T) => string | null)
| ((t: T) => boolean | null)
| ((t: T) => Date | null)
| ((t: T) => ComparableObj | null);
A function which converts or extracts a comparable value
This is used primarily by LazySeq to extract comparable values from an object for grouping.
export type ToComparable<T> =
| { asc: ToComparableBase<T> }
| { desc: ToComparableBase<T> }
| ToComparableBase<T>;
A function which converts or extracts a comparable value and a direction
This is used primarily by LazySeq to extract comparable values from an object for grouping, while also allowing you to specify if the ordering should be in ascending or descending order. For example, see LazySeq.distinctAndSortBy.
Hash Utils
The possible types for a key in a HashMap
Interface allowing custom key objects in a HashMap
If you wish to use a custom object as a key in a HashMap, you must implement the hash
function
defined in the HashableObj type and the compare
function defined in the ComparableObj type.
The hash value must be a 32-bit integer. The hashValues function can help implementing
the hash function.
Example
class SomeKey {
public readonly a: number;
public readonly b: string;
constructor(a: number, b: string) {
this.a = a;
this.b = b;
}
hash(): number {
return hashValues(this.a, this.b);
}
compare(other: SomeKey): number {
return (this.a - other.a) || this.b.localeCompare(other.b);
}
}
function hashValues(
...vals: ReadonlyArray<
string | number | boolean | Date | HashableObj | null | undefined
>
): number
Combine multiple hashable values into a single hash
Useful helper function to hash multiple values to a single hash. This uses the FNV-1 hash function, which is NOT secure. If you need a secure hash, use something like highwayhash and implement a custom HashableObj interface.
export type ToHashable<T> =
| ((t: T) => number | null)
| ((t: T) => string | null)
| ((t: T) => boolean | null)
| ((t: T) => Date | null)
| ((t: T) => (HashableObj & ComparableObj) | null);
A function which converts or extracts a hashable value
This is used primarily by LazySeq to extract hashable values from an object for grouping. For example, see LazySeq.groupBy.