alistair
Version:
538 lines (532 loc) • 14.2 kB
JavaScript
'use strict';
var chunkMLRVSOE7_cjs = require('../chunk-MLRVSOE7.cjs');
// Copyright 2025 Alistair Smith https://github.com/alii/alistair
// src/structs/immutable-map.ts
var ImmutableMap = class _ImmutableMap {
/**
* Internal Map instance used for storage
* @private
*/
map = /* @__PURE__ */ new Map();
/**
* A shared empty immutable map instance. Using `never` type ensures
* it can be safely cast to ImmutableMap<K, V> for any K and V.
*
* @example
* ```typescript
* const emptyStringMap = ImmutableMap.Empty as ImmutableMap<string, number>;
* const emptyUserMap = ImmutableMap.Empty as ImmutableMap<UserId, User>;
* ```
*/
static Empty = new _ImmutableMap();
/**
* Creates a new ImmutableMap instance, optionally from an iterable
*
* This is perfect for usage with `useState` as React calls the `.from()` function
* when initializing the state, but TypeScript lets us set the generic types
* inline.
*
* @example
* ```typescript
* const [map, setMap] = useState(ImmutableMap.from<string, number>);
* ```
*
* @param iterable - Optional iterable of initial [key, value] pairs
* @returns A new ImmutableMap instance
*/
static from = (iterable) => new _ImmutableMap(iterable);
/**
* Returns the number of key/value pairs in the map
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* console.log(map.size); // 2
* ```
*/
get size() {
return this.map.size;
}
/**
* Creates a new ImmutableMap instance
*
* @param iterable - Optional iterable of initial [key, value] pairs
*
* @example
* ```typescript
* const map1 = new ImmutableMap([['a', 1], ['b', 2]]);
* const map2 = new ImmutableMap(new Map([['x', 10], ['y', 20]]));
* const empty = new ImmutableMap<string, number>();
* ```
*/
constructor(iterable) {
this.map = new Map(iterable);
}
/**
* Creates a new map with the specified key/value pair added or updated
*
* @param key - The key to set
* @param value - The value to associate with the key
* @returns A new ImmutableMap containing the new key/value pair
*
* @example
* ```typescript
* const map1 = new ImmutableMap([['a', 1]]);
* const map2 = map1.set('b', 2);
* const map3 = map2.set('a', 10); // Updates existing key
*
* console.log(map1.get('b')); // undefined
* console.log(map2.get('b')); // 2
* console.log(map3.get('a')); // 10
* ```
*/
set(key, value) {
return this.mutate((map) => {
map.set(key, value);
});
}
/**
* Retrieves the value associated with a key
*
* @param key - The key to look up
* @returns The value associated with the key, or undefined if the key doesn't exist
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* console.log(map.get('a')); // 1
* console.log(map.get('x')); // undefined
* ```
*/
get(key) {
return this.map.get(key);
}
/**
* Checks if a key exists in the map
*
* @param key - The key to check
* @returns `true` if the key exists, `false` otherwise
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* console.log(map.has('a')); // true
* console.log(map.has('x')); // false
* ```
*/
has(key) {
return this.map.has(key);
}
/**
* Creates a new map with the specified key removed
*
* @param key - The key to remove
* @returns A new ImmutableMap with the key/value pair removed
*
* @example
* ```typescript
* const map1 = new ImmutableMap([['a', 1], ['b', 2]]);
* const map2 = map1.delete('a');
*
* console.log(map1.has('a')); // true
* console.log(map2.has('a')); // false
* ```
*/
delete(key) {
return this.mutate((map) => {
map.delete(key);
});
}
/**
* Creates a new empty map
*
* @returns A new empty ImmutableMap
*
* @example
* ```typescript
* const map1 = new ImmutableMap([['a', 1], ['b', 2]]);
* const map2 = map1.clear();
*
* console.log(map1.size); // 2
* console.log(map2.size); // 0
* ```
*/
clear() {
return _ImmutableMap.Empty;
}
/**
* Executes a callback for each key/value pair in the map
*
* @param callbackfn - Function to execute for each entry
* @param thisArg - Value to use as `this` when executing the callback
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* const results: string[] = [];
* map.forEach((value, key) => {
* results.push(`${key}=${value}`);
* });
* console.log(results); // ['a=1', 'b=2']
* ```
*/
forEach(callbackfn, thisArg) {
this.map.forEach(callbackfn, thisArg);
}
/**
* Returns an iterator of the map's keys
*
* @returns An iterator containing the keys
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* const keys = [...map.keys()];
* console.log(keys); // ['a', 'b']
* ```
*/
keys() {
return this.map.keys();
}
/**
* Returns an iterator of the map's values
*
* @returns An iterator containing the values
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* const values = [...map.values()];
* console.log(values); // [1, 2]
* ```
*/
values() {
return this.map.values();
}
/**
* Returns an iterator of the map's entries
*
* @returns An iterator containing [key, value] pairs
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* for (const [key, value] of map.entries()) {
* console.log(`${key}=${value}`); // Logs: 'a=1', then 'b=2'
* }
* ```
*/
entries() {
return this.map.entries();
}
/**
* Implements the iterable protocol, allowing the map to be used with for...of loops
*
* @returns An iterator containing [key, value] pairs
*
* @example
* ```typescript
* const map = new ImmutableMap([['a', 1], ['b', 2]]);
* for (const [key, value] of map) {
* console.log(`${key}=${value}`); // Logs: 'a=1', then 'b=2'
* }
* ```
*/
[Symbol.iterator]() {
return this.map[Symbol.iterator]();
}
/**
* Customizes the string tag for the ImmutableMap instance
* Used in Object.prototype.toString.call(immutableMap)
*
* @example
* ```typescript
* const map = new ImmutableMap();
* console.log(Object.prototype.toString.call(map)); // '[object ImmutableMap]'
* ```
*/
get [Symbol.toStringTag]() {
return "ImmutableMap";
}
/**
* Internal helper method for creating new instances when performing
* mutations. This ensures immutability while allowing reuse of logic.
*
* @param fn - Function that performs the mutation on the cloned map
* @returns A new ImmutableMap instance with the mutation applied
* @private
*/
mutate(fn) {
const clone = new _ImmutableMap(this.map);
fn(clone.map);
return clone;
}
};
// src/structs/immutable-set.ts
var ImmutableSet = class _ImmutableSet {
/**
* Internal Set instance used for storage
* @private
*/
set = /* @__PURE__ */ new Set();
/**
* A shared empty immutable set instance. Using `never` type ensures
* it can be safely cast to ImmutableSet<T> for any T.
*
* @example
* ```typescript
* const emptyStrings = ImmutableSet.Empty as ImmutableSet<string>;
* const emptyNumbers = ImmutableSet.Empty as ImmutableSet<number>;
* ```
*
* You can also use this
*/
static Empty = new _ImmutableSet();
/**
* Creates a new ImmutableSet instance, optionally from an iterable
*
* This is perfect for usage with `useState` as React calls the `.from()` function
* when initializing the state, but TypeScript lets us set the generic type
* inline.
*
* ```typescript
* const [set, setState] = useState(ImmutableSet.from<string>);
* ```
*
* @param iterable - Optional iterable of initial values
* @returns A new ImmutableSet instance
*/
static from = (iterable) => new _ImmutableSet(iterable);
/**
* Creates a new ImmutableSet instance
*
* @param iterable - Optional iterable of initial values
*
* @example
* ```typescript
* const set1 = new ImmutableSet(['a', 'b', 'c']);
* const set2 = new ImmutableSet(new Set([1, 2, 3]));
* const empty = new ImmutableSet<string>();
* ```
*/
constructor(iterable) {
this.set = new Set(iterable);
}
/**
* Internal helper method for creating new instances when performing
* mutations. This ensures immutability while allowing reuse of logic.
*
* @param fn - Function that performs the mutation on the cloned set
* @returns A new ImmutableSet instance with the mutation applied
* @private
*/
mutate(fn) {
const clone = new _ImmutableSet(this.set);
fn(clone.set);
return clone;
}
/**
* Creates a new set with the specified value added
*
* @param value - The value to add
* @returns A new ImmutableSet containing the added value
*
* @example
* ```typescript
* const set1 = new ImmutableSet(['a', 'b']);
* const set2 = set1.add('c');
* console.log([...set2]); // ['a', 'b', 'c']
* console.log(set1 === set2); // false
* ```
*/
add(value) {
return this.mutate((set) => {
set.add(value);
});
}
/**
* Creates a new empty set, discarding all current values
*
* @returns The empty ImmutableSet singleton instance
*
* @example
* ```typescript
* const set1 = new ImmutableSet(['a', 'b']);
* const set2 = set1.clear();
* console.log(set2.size); // 0
* console.log(set2 === ImmutableSet.Empty); // true
* ```
*/
clear() {
return _ImmutableSet.Empty;
}
/**
* Creates a new set with the specified value removed
*
* @param value - The value to remove
* @returns A new ImmutableSet with the value removed
*
* @example
* ```typescript
* const set1 = new ImmutableSet(['a', 'b', 'c']);
* const set2 = set1.delete('b');
* console.log([...set2]); // ['a', 'c']
* console.log(set1.has('b')); // true
* ```
*/
delete(value) {
return this.mutate((set) => {
set.delete(value);
});
}
/**
* Executes a callback for each value in the set
*
* @param callbackfn - Function to execute for each value
* @param thisArg - Value to use as `this` when executing the callback
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b', 'c']);
* const results: string[] = [];
* set.forEach(value => results.push(value.toUpperCase()));
* console.log(results); // ['A', 'B', 'C']
* ```
*/
forEach(callbackfn, thisArg) {
return this.set.forEach(callbackfn, thisArg);
}
/**
* Toggles a value in the set, adding it if it doesn't exist or removing it if it does
*
* @param value - The value to toggle
* @returns A new ImmutableSet with the value toggled
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b']);
* const set2 = set.toggle('c');
* console.log([...set2]); // ['a', 'b', 'c']
* ```
*
* This is super helpful with React state management because the methods return a new instance
* and it means React knows the state has changed.
*
* ```tsx
* const [state, setState] = useState(ImmutableSet.from<string>)
* <button onClick={() => setState(old => old.toggle('c'))}>Toggle c</button>
* ```
*/
toggle(value) {
return this.has(value) ? this.delete(value) : this.add(value);
}
/**
* Checks if a value exists in the set
*
* @param value - The value to check
* @returns `true` if the value exists, `false` otherwise
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b']);
* console.log(set.has('a')); // true
* console.log(set.has('c')); // false
* ```
*/
has(value) {
return this.set.has(value);
}
/**
* Returns an iterator of [value, value] pairs
*
* @returns An iterator containing pairs of values
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b']);
* for (const [value1, value2] of set.entries()) {
* console.log(value1 === value2); // true
* }
* ```
*/
entries() {
return this.set.entries();
}
/**
* Returns an iterator of values (identical to values())
*
* @returns An iterator containing the values
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b']);
* const keys = [...set.keys()];
* console.log(keys); // ['a', 'b']
* ```
*/
keys() {
return this.set.keys();
}
/**
* Returns an iterator of values
*
* @returns An iterator containing the values
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b']);
* const values = [...set.values()];
* console.log(values); // ['a', 'b']
* ```
*/
values() {
return this.set.values();
}
/**
* Implements the iterable protocol, allowing the set to be used with for...of loops
*
* @returns An iterator containing the values
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b']);
* for (const value of set) {
* console.log(value); // 'a', then 'b'
* }
* ```
*/
[Symbol.iterator]() {
return this.set[Symbol.iterator]();
}
/**
* Customizes the string tag for the ImmutableSet instance
* Used in Object.prototype.toString.call(immutableSet)
*
* @example
* ```typescript
* const set = new ImmutableSet();
* console.log(Object.prototype.toString.call(set)); // '[object ImmutableSet]'
* ```
*/
get [Symbol.toStringTag]() {
return "ImmutableSet";
}
/**
* Returns the number of values in the set
*
* @example
* ```typescript
* const set = new ImmutableSet(['a', 'b']);
* console.log(set.size); // 2
* ```
*/
get size() {
return this.set.size;
}
};
Object.defineProperty(exports, "StrictMap", {
enumerable: true,
get: function () { return chunkMLRVSOE7_cjs.StrictMap; }
});
exports.ImmutableMap = ImmutableMap;
exports.ImmutableSet = ImmutableSet;