ts-data-forge
Version:
[](https://www.npmjs.com/package/ts-data-forge) [](https://www.npmjs.com/package/ts-data-forge) [ average case (plus element transformation overhead)
* - add/delete: O(n) due to copying for immutability (plus element
* transformation overhead)
* - set operations (union, intersection, difference): O(n)
* - map/filter operations: O(n)
* - iteration: O(n) (plus element transformation overhead)
*
* @template K The type of the custom elements in the set.
* @template KM The type of the mapped primitive keys (string, number, etc.).
*/
type ISetMappedInterface<K, KM extends MapSetKeyType> = Readonly<{
/**
* Creates a new ISetMapped instance.
*
* @param iterable An iterable of elements.
* @param toKey A function that converts an element of type `K` to `KM`.
* @param fromKey A function that converts a mapped key of type `KM` back to
* `K`.
*/
new (iterable: Iterable<K>, toKey: (a: K) => KM, fromKey: (k: KM) => K): void;
/**
* The number of elements in the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const points: readonly Point[] = [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ];
*
* const set = ISetMapped.create<Point, string>(points, toKey, fromKey);
*
* assert.isTrue(set.size === 2);
* ```
*/
size: SizeType.Arr;
/**
* Checks if the set is empty.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const empty = ISetMapped.create<Point, string>([], toKey, fromKey);
*
* const points = ISetMapped.create<Point, string>(
* [{ x: 1, tag: 'a' }],
* toKey,
* fromKey,
* );
*
* assert.isTrue(empty.isEmpty);
*
* assert.isFalse(points.isEmpty);
* ```
*/
isEmpty: boolean;
/**
* Checks if an element exists in the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [{ x: 1, tag: 'a' }],
* toKey,
* fromKey,
* );
*
* assert.isTrue(set.has({ x: 1, tag: 'a' }));
*
* assert.isFalse(set.has({ x: 2, tag: 'b' }));
* ```
*
* @param key The element to check.
* @returns `true` if the element exists, `false` otherwise.
*/
has: (key: K) => boolean;
/**
* Checks if all elements in the set satisfy a predicate.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 2, tag: 'even' },
* { x: 4, tag: 'even' },
* ],
* toKey,
* fromKey,
* );
*
* const allEven = set.every((point) => point.x % 2 === 0);
*
* const narrowed = set.every(
* (point): point is Readonly<{ x: 2 | 4; tag: 'even' }> => point.x % 2 === 0,
* );
*
* assert.isTrue(allEven);
*
* assert.isTrue(narrowed);
* ```
*
* @param predicate A function to test each element.
* @returns `true` if all elements satisfy the predicate, `false` otherwise.
*/
every: ((predicate: (key: K) => boolean) => boolean) &
/**
* Checks if all elements in the set satisfy a type predicate. Narrows the
* type of elements in the set if the predicate returns true for all
* elements.
*
* @template L The narrowed type of the elements.
* @param predicate A type predicate function.
* @returns `true` if all elements satisfy the predicate, `false` otherwise.
*/
(<L extends K>(predicate: (key: K) => key is L) => this is ISetMapped<L, KM>);
/**
* Checks if at least one element in the set satisfies a predicate.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 5, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* assert.isTrue(set.some((point) => point.x > 4));
*
* assert.isFalse(set.some((point) => point.x > 10));
* ```
*
* @param predicate A function to test each element.
* @returns `true` if at least one element satisfies the predicate, `false`
* otherwise.
*/
some: (predicate: (key: K) => boolean) => boolean;
/**
* Adds an element to the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const base = ISetMapped.create<Point, string>(
* [{ x: 1, tag: 'a' }],
* toKey,
* fromKey,
* );
*
* const withNew = base.add({ x: 2, tag: 'b' });
*
* const unchanged = base.add({ x: 1, tag: 'a' });
*
* assert.deepStrictEqual(Array.from(withNew), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
*
* assert.isTrue(unchanged === base);
* ```
*
* @param key The element to add.
* @returns A new ISetMapped instance with the element added.
*/
add: (key: K) => ISetMapped<K, KM>;
/**
* Deletes an element from the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const base = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const withoutSecond = base.delete({ x: 2, tag: 'b' });
*
* const unchanged = base.delete({ x: 3, tag: 'c' });
*
* assert.deepStrictEqual(Array.from(withoutSecond), [{ x: 1, tag: 'a' }]);
*
* assert.isTrue(unchanged === base);
* ```
*
* @param key The element to delete.
* @returns A new ISetMapped instance without the specified element.
*/
delete: (key: K) => ISetMapped<K, KM>;
/**
* Applies a series of mutations to the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const base = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const actions: readonly Readonly<
* { type: 'add'; key: Point } | { type: 'delete'; key: Point }
* >[] = [
* { type: 'add', key: { x: 3, tag: 'c' } },
* { type: 'delete', key: { x: 1, tag: 'a' } },
* ];
*
* const mutated = base.withMutations(actions);
*
* assert.deepStrictEqual(Array.from(mutated), [
* { x: 2, tag: 'b' },
* { x: 3, tag: 'c' },
* ]);
*
* assert.deepStrictEqual(Array.from(base), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @param actions An array of mutation actions (add or delete).
* @returns A new ISetMapped instance with all mutations applied.
*/
withMutations: (actions: readonly Readonly<{
type: 'add';
key: K;
} | {
type: 'delete';
key: K;
}>[]) => ISetMapped<K, KM>;
/**
* Maps the elements of the set to new elements. Note: The element type `K`
* cannot be changed because `toKey` and `fromKey` would become unusable if
* the mapped type `KM` changes.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const shifted = set.map((point) => ({
* x: point.x + 10,
* tag: point.tag.toUpperCase(),
* }));
*
* assert.deepStrictEqual(Array.from(shifted), [
* { x: 11, tag: 'A' },
* { x: 12, tag: 'B' },
* ]);
* ```
*
* @param mapFn A function that maps an element to a new element of the same
* type `K`.
* @returns A new ISetMapped instance with mapped elements.
*/
map: (mapFn: (key: K) => K) => ISetMapped<K, KM>;
/**
* Filters the elements of the set based on a predicate.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* { x: 3, tag: 'c' },
* ],
* toKey,
* fromKey,
* );
*
* const evenPoints = set.filter((point) => point.x % 2 === 0);
*
* assert.deepStrictEqual(Array.from(evenPoints), [{ x: 2, tag: 'b' }]);
* ```
*
* @param predicate A function to test each element.
* @returns A new ISetMapped instance with elements that satisfy the
* predicate.
*/
filter: (predicate: (value: K) => boolean) => ISetMapped<K, KM>;
/**
* Filters the elements of the set by excluding elements for which the
* predicate returns true.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const withoutEven = set.filterNot((point) => point.x % 2 === 0);
*
* assert.deepStrictEqual(Array.from(withoutEven), [{ x: 1, tag: 'a' }]);
* ```
*
* @param predicate A function to test each element.
* @returns A new ISetMapped instance with elements for which the predicate
* returned `false`.
*/
filterNot: (predicate: (key: K) => boolean) => ISetMapped<K, KM>;
/**
* Executes a callback function for each element in the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const collected: Point[] = [];
*
* for (const point of set) {
* collected.push(point);
* }
*
* assert.deepStrictEqual(collected, [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @param callbackfn A function to execute for each element.
*/
forEach: (callbackfn: (key: K) => void) => void;
/**
* Checks if this set is a subset of another set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const subset = ISetMapped.create<Point, string>(
* [{ x: 1, tag: 'a' }],
* toKey,
* fromKey,
* );
*
* const superset = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* assert.isTrue(subset.isSubsetOf(superset));
*
* assert.isFalse(superset.isSubsetOf(subset));
* ```
*
* @param set The other set.
* @returns `true` if this set is a subset of the other set, `false`
* otherwise.
*/
isSubsetOf: (set: ISetMapped<K, KM>) => boolean;
/**
* Checks if this set is a superset of another set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const superset = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const subset = ISetMapped.create<Point, string>(
* [{ x: 2, tag: 'b' }],
* toKey,
* fromKey,
* );
*
* assert.isTrue(superset.isSupersetOf(subset));
*
* assert.isFalse(subset.isSupersetOf(superset));
* ```
*
* @param set The other set.
* @returns `true` if this set is a superset of the other set, `false`
* otherwise.
*/
isSupersetOf: (set: ISetMapped<K, KM>) => boolean;
/**
* Returns a new set with elements that are in this set but not in another
* set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const left = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* { x: 3, tag: 'c' },
* ],
* toKey,
* fromKey,
* );
*
* const right = ISetMapped.create<Point, string>(
* [{ x: 2, tag: 'b' }],
* toKey,
* fromKey,
* );
*
* const difference = left.subtract(right);
*
* assert.deepStrictEqual(Array.from(difference), [
* { x: 1, tag: 'a' },
* { x: 3, tag: 'c' },
* ]);
* ```
*
* @param set The other set.
* @returns A new ISetMapped instance representing the set difference.
*/
subtract: (set: ISetMapped<K, KM>) => ISetMapped<K, KM>;
/**
* Returns a new set with elements that are common to both this set and
* another set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const left = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const right = ISetMapped.create<Point, string>(
* [{ x: 2, tag: 'b' }],
* toKey,
* fromKey,
* );
*
* const intersection = left.intersect(right);
*
* assert.deepStrictEqual(Array.from(intersection), [{ x: 2, tag: 'b' }]);
* ```
*
* @param set The other set.
* @returns A new ISetMapped instance representing the set intersection.
*/
intersect: (set: ISetMapped<K, KM>) => ISetMapped<K, KM>;
/**
* Returns a new set with all elements from both this set and another set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const left = ISetMapped.create<Point, string>(
* [{ x: 1, tag: 'a' }],
* toKey,
* fromKey,
* );
*
* const right = ISetMapped.create<Point, string>(
* [{ x: 2, tag: 'b' }],
* toKey,
* fromKey,
* );
*
* const combined = left.union(right);
*
* assert.deepStrictEqual(Array.from(combined), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @param set The other set.
* @returns A new ISetMapped instance representing the set union.
*/
union: (set: ISetMapped<K, KM>) => ISetMapped<K, KM>;
/**
* Returns an iterator for the elements in the set (alias for values).
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* assert.deepStrictEqual(Array.from(set.keys()), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @returns An iterable iterator of elements.
*/
keys: () => IterableIterator<K>;
/**
* Returns an iterator for the elements in the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* assert.deepStrictEqual(Array.from(set.values()), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @returns An iterable iterator of elements.
*/
values: () => IterableIterator<K>;
/**
* Returns an iterator for the entries (element-element pairs) in the set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* assert.deepStrictEqual(Array.from(set.entries()), [
* [
* { x: 1, tag: 'a' },
* { x: 1, tag: 'a' },
* ],
* [
* { x: 2, tag: 'b' },
* { x: 2, tag: 'b' },
* ],
* ]);
* ```
*
* @returns An iterable iterator of entries.
*/
entries: () => IterableIterator<readonly [K, K]>;
/**
* Converts the elements of the set to an array.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* assert.deepStrictEqual(set.toArray(), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @returns A readonly array of elements.
*/
toArray: () => readonly K[];
/**
* Returns the underlying readonly JavaScript Set of mapped keys.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [{ x: 1, tag: 'a' }],
* toKey,
* fromKey,
* );
*
* const raw = set.toRawSet();
*
* assert.isTrue(is.set(raw));
*
* assert.isTrue(raw.has(toKey({ x: 1, tag: 'a' })));
* ```
*
* @returns The raw ReadonlySet instance.
*/
toRawSet: () => ReadonlySet<KM>;
}>;
/**
* Represents an immutable set with custom element transformation and
* high-performance operations.
*
* ISetMapped is a specialized persistent data structure that enables using
* complex objects as set elements while maintaining the performance benefits of
* JavaScript's native Set. It achieves this by requiring bidirectional
* transformation functions that convert between your custom element type and a
* primitive type that can be efficiently stored and compared for uniqueness.
*
* **Key Features:**
*
* - **Complex Elements**: Use objects, arrays, or any custom type as set elements
* - **Immutable**: All mutation operations return new instances
* - **Type Safe**: Full TypeScript support with compile-time element type
* checking
* - **Bidirectional**: Maintains ability to reconstruct original elements from
* mapped keys
* - **Set Algebra**: Complete support for mathematical set operations
*
* **Use Cases:**
*
* - Sets of entities with complex identifiers
* - Deduplication of objects based on specific properties
* - Performance-critical sets with non-primitive elements
* - Mathematical set operations on complex data structures
*
* @template K The type of the custom elements in the set.
* @template KM The type of the mapped primitive keys (string, number, etc.).
*/
export type ISetMapped<K, KM extends MapSetKeyType> = Iterable<K> & Readonly<ISetMappedInterface<K, KM>>;
/** Provides utility functions for ISetMapped. */
export declare namespace ISetMapped {
/**
* Creates a new ISetMapped instance with custom element transformation
* functions.
*
* This factory function creates an immutable set that can use complex objects
* as elements by providing bidirectional transformation functions. The
* `toKey` function converts your custom element type to a primitive type that
* can be efficiently stored, while `fromKey` reconstructs the original
* element type for iteration and access.
*
* **Performance:** O(n) where n is the number of elements in the iterable.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const set = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* assert.deepStrictEqual(Array.from(set), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @template K The type of the custom elements.
* @template KM The type of the mapped primitive keys.
* @param iterable An iterable of elements using the custom element type.
* @param toKey A function that converts a custom element `K` to a primitive
* key `KM`. This function must be deterministic and produce unique values
* for unique elements.
* @param fromKey A function that converts a primitive key `KM` back to the
* custom element `K`. This should be the inverse of `toKey`.
* @returns A new ISetMapped instance containing all unique elements from the
* iterable.
*/
const create: <K, KM extends MapSetKeyType>(iterable: Iterable<K>, toKey: (a: K) => KM, fromKey: (k: KM) => K) => ISetMapped<K, KM>;
/**
* Checks if two ISetMapped instances are structurally equal.
*
* Two ISetMapped instances are considered equal if they have the same size
* and contain exactly the same elements. The comparison is performed on the
* underlying mapped keys, so the transformation functions themselves don't
* need to be identical. Elements are compared based on their mapped key
* representations.
*
* **Performance:** O(n) where n is the size of the smaller set.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const first = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const second = ISetMapped.create<Point, string>(
* [
* { x: 2, tag: 'b' },
* { x: 1, tag: 'a' },
* ],
* toKey,
* fromKey,
* );
*
* const third = ISetMapped.create<Point, string>(
* [{ x: 3, tag: 'c' }],
* toKey,
* fromKey,
* );
*
* assert.isTrue(ISetMapped.equal(first, second));
*
* assert.isFalse(ISetMapped.equal(first, third));
* ```
*
* @template K The type of the custom elements.
* @template KM The type of the mapped primitive keys.
* @param a The first ISetMapped instance to compare.
* @param b The second ISetMapped instance to compare.
* @returns `true` if the sets contain exactly the same elements, `false`
* otherwise.
*/
const equal: <K, KM extends MapSetKeyType>(a: ISetMapped<K, KM>, b: ISetMapped<K, KM>) => boolean;
/**
* Computes the difference between two ISetMapped instances.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const previous = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const current = ISetMapped.create<Point, string>(
* [
* { x: 2, tag: 'b' },
* { x: 3, tag: 'c' },
* ],
* toKey,
* fromKey,
* );
*
* const { added, deleted } = ISetMapped.diff(previous, current);
*
* assert.deepStrictEqual(Array.from(added), [{ x: 3, tag: 'c' }]);
*
* assert.deepStrictEqual(Array.from(deleted), [{ x: 1, tag: 'a' }]);
* ```
*
* @template K The type of the elements.
* @template KM The type of the mapped keys.
* @param oldSet The original set.
* @param newSet The new set.
* @returns An object containing sets of added and deleted elements.
*/
const diff: <K, KM extends MapSetKeyType>(oldSet: ISetMapped<K, KM>, newSet: ISetMapped<K, KM>) => ReadonlyRecord<"added" | "deleted", ISetMapped<K, KM>>;
/**
* Computes the intersection of two ISetMapped instances.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const left = ISetMapped.create<Point, string>(
* [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ],
* toKey,
* fromKey,
* );
*
* const right = ISetMapped.create<Point, string>(
* [{ x: 2, tag: 'b' }],
* toKey,
* fromKey,
* );
*
* const overlap = ISetMapped.intersection(left, right);
*
* assert.deepStrictEqual(Array.from(overlap), [{ x: 2, tag: 'b' }]);
* ```
*
* @template K The type of the elements.
* @template KM The type of the mapped keys.
* @param a The first set.
* @param b The second set.
* @returns A new ISetMapped instance representing the intersection.
*/
const intersection: <K, KM extends MapSetKeyType>(a: ISetMapped<K, KM>, b: ISetMapped<K, KM>) => ISetMapped<K, KM>;
/**
* Computes the union of two ISetMapped instances.
*
* @example
*
* ```ts
* type Point = Readonly<{ x: number; tag: string }>;
*
* const toKey = (point: Point) => JSON.stringify(point);
*
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
* const fromKey = (key: string) => JSON.parse(key) as Point;
*
* const left = ISetMapped.create<Point, string>(
* [{ x: 1, tag: 'a' }],
* toKey,
* fromKey,
* );
*
* const right = ISetMapped.create<Point, string>(
* [{ x: 2, tag: 'b' }],
* toKey,
* fromKey,
* );
*
* const combined = ISetMapped.union(left, right);
*
* assert.deepStrictEqual(Array.from(combined), [
* { x: 1, tag: 'a' },
* { x: 2, tag: 'b' },
* ]);
* ```
*
* @template K The type of the elements.
* @template KM The type of the mapped keys.
* @param a The first set.
* @param b The second set.
* @returns A new ISetMapped instance representing the union.
*/
const union: <K, KM extends MapSetKeyType>(a: ISetMapped<K, KM>, b: ISetMapped<K, KM>) => ISetMapped<K, KM>;
}
export {};
//# sourceMappingURL=iset-mapped.d.mts.map