ts-data-forge 14.0.0 → 14.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +3 -2
  2. package/dist/array/impl/array-utils-modification.d.mts +18 -5
  3. package/dist/array/impl/array-utils-modification.d.mts.map +1 -1
  4. package/dist/array/impl/array-utils-modification.mjs.map +1 -1
  5. package/dist/array/impl/array-utils-slice-clamped.d.mts.map +1 -1
  6. package/dist/array/impl/array-utils-slice-clamped.mjs.map +1 -1
  7. package/dist/array/impl/array-utils-transformation.d.mts +8 -3
  8. package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
  9. package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
  10. package/dist/collections/imap.d.mts +1 -1
  11. package/dist/collections/imap.mjs.map +1 -1
  12. package/dist/collections/iset-mapped.d.mts +2 -2
  13. package/dist/collections/iset-mapped.d.mts.map +1 -1
  14. package/dist/collections/iset-mapped.mjs.map +1 -1
  15. package/dist/collections/iset.d.mts +2 -2
  16. package/dist/collections/iset.d.mts.map +1 -1
  17. package/dist/collections/iset.mjs.map +1 -1
  18. package/dist/number/num-arithmetic-types.d.mts +2 -2
  19. package/dist/number/num-arithmetic-types.d.mts.map +1 -1
  20. package/package.json +4 -5
  21. package/src/array/impl/array-utils-creation.test.mts +10 -8
  22. package/src/array/impl/array-utils-length-constraint-preservation.test.mts +2 -2
  23. package/src/array/impl/array-utils-modification.mts +41 -33
  24. package/src/array/impl/array-utils-modification.test.mts +52 -0
  25. package/src/array/impl/array-utils-shape-invariants.test.mts +284 -0
  26. package/src/array/impl/array-utils-slice-clamped.mts +2 -1
  27. package/src/array/impl/array-utils-transformation.mts +29 -2
  28. package/src/array/impl/array-utils-transformation.test.mts +34 -7
  29. package/src/collections/imap.mts +1 -1
  30. package/src/collections/iset-mapped.mts +7 -3
  31. package/src/collections/iset.mts +7 -3
  32. package/src/collections/iset.test.mts +9 -6
  33. package/src/number/num-arithmetic-types.mts +8 -4
  34. package/src/number/num.test.mts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"iset.mjs","sources":["../../src/collections/iset.mts"],"sourcesContent":["/* eslint-disable unicorn/prefer-iterator-to-array-at-end */\nimport { type ReadonlyRecord, type WidenLiteral } from 'ts-type-forge';\nimport { asUint32 } from '../number/index.mjs';\nimport { unknownToString } from '../others/index.mjs';\nimport { type MapSetKeyType, type SizeType } from '../types.mjs';\n\n/**\n * Interface for an immutable set with membership testing and set operation\n * support.\n *\n * This interface defines all methods and properties available on ISet\n * instances. All operations that modify the set return new ISet instances,\n * preserving immutability. The underlying implementation uses JavaScript's\n * native Set but creates copies on mutations to maintain immutability.\n *\n * **Immutability Guarantees:**\n *\n * - All mutation operations (add, delete) return new ISet instances\n * - Original ISet instances are never modified\n * - Safe for concurrent access and functional programming patterns\n *\n * **Performance Characteristics:**\n *\n * - has: O(1) average case\n * - add/delete: O(n) due to copying for immutability\n * - set operations (union, intersection, difference): O(n)\n * - map/filter operations: O(n)\n * - iteration: O(n)\n *\n * @template K The type of the elements in the set. Must extend MapSetKeyType\n * (string, number, boolean, etc.)\n */\ntype ISetInterface<K extends MapSetKeyType> = Readonly<{\n // Getting information\n\n /**\n * The number of elements in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create([1, 2, 3]);\n *\n * assert.isTrue(set.size === 3);\n * ```\n */\n size: SizeType.Arr;\n\n /**\n * Checks if the set is empty.\n *\n * @example\n *\n * ```ts\n * const emptySet = ISet.create<number>([]);\n *\n * const filledSet = ISet.create([1, 2]);\n *\n * assert.isTrue(emptySet.isEmpty);\n *\n * assert.isFalse(filledSet.isEmpty);\n * ```\n */\n isEmpty: boolean;\n\n /**\n * Checks if an element exists in the set. Allows for wider literal types for\n * keys during checking.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['apple', 'banana']);\n *\n * assert.isTrue(set.has('apple'));\n *\n * assert.isFalse(set.has('cherry'));\n * ```\n *\n * @param key The element to check.\n * @returns `true` if the element exists, `false` otherwise.\n */\n has: (key: K | (WidenLiteral<K> & {})) => boolean;\n\n // Reducing a value\n\n /**\n * Checks if all elements in the set satisfy a predicate. Also supports a\n * type predicate overload that narrows the type of elements in the set if\n * the predicate returns true for all elements.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([2, 4, 6]);\n *\n * const allEven = numbers.every((value) => value % 2 === 0);\n *\n * const narrowed = numbers.every(\n * (value): value is 2 | 4 | 6 => value % 2 === 0,\n * );\n *\n * assert.isTrue(allEven);\n *\n * assert.isTrue(narrowed);\n * ```\n *\n * @template L The narrowed type of the elements.\n * @param predicate A function to test each element.\n * @returns `true` if all elements satisfy the predicate, `false` otherwise.\n */\n every: ((predicate: (key: K) => boolean) => boolean) &\n (<L extends K>(predicate: (key: K) => key is L) => this is ISet<L>);\n\n /**\n * Checks if at least one element in the set satisfies a predicate.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 3, 5]);\n *\n * assert.isTrue(numbers.some((value) => value > 4));\n *\n * assert.isFalse(numbers.some((value) => value > 10));\n * ```\n *\n * @param predicate A function to test each element.\n * @returns `true` if at least one element satisfies the predicate, `false`\n * otherwise.\n */\n some: (predicate: (key: K) => boolean) => boolean;\n\n // Mutation\n\n /**\n * Adds an element to the set.\n *\n * @example\n *\n * ```ts\n * const base = ISet.create<number>([1, 2]);\n *\n * const withThree = base.add(3);\n *\n * const unchanged = base.add(2);\n *\n * assert.deepStrictEqual(Array.from(withThree), [1, 2, 3]);\n *\n * assert.isTrue(unchanged === base);\n * ```\n *\n * @param key The element to add.\n * @returns A new ISet instance with the element added.\n */\n add: (key: K) => ISet<K>;\n\n /**\n * Deletes an element from the set.\n *\n * @example\n *\n * ```ts\n * const base = ISet.create<number>([1, 2, 3]);\n *\n * const withoutTwo = base.delete(2);\n *\n * const unchanged = base.delete(4);\n *\n * assert.deepStrictEqual(Array.from(withoutTwo), [1, 3]);\n *\n * assert.isTrue(unchanged === base);\n * ```\n *\n * @param key The element to delete.\n * @returns A new ISet instance without the specified element.\n */\n delete: (key: K) => ISet<K>;\n\n /**\n * Applies a series of mutations to the set.\n *\n * @example\n *\n * ```ts\n * const base = ISet.create<string>(['a', 'b']);\n *\n * const actions: readonly Readonly<\n * { type: 'add'; key: string } | { type: 'delete'; key: string }\n * >[] = [\n * { type: 'add', key: 'c' },\n * { type: 'delete', key: 'a' },\n * ] as const;\n *\n * const mutated = base.withMutations(actions);\n *\n * assert.deepStrictEqual(Array.from(mutated), ['b', 'c']);\n *\n * assert.deepStrictEqual(Array.from(base), ['a', 'b']);\n * ```\n *\n * @param actions An array of mutation actions (add or delete).\n * @returns A new ISet instance with all mutations applied.\n */\n withMutations: (\n actions: readonly Readonly<\n { type: 'add'; key: K } | { type: 'delete'; key: K }\n >[],\n ) => ISet<K>;\n\n // Sequence algorithms\n\n /**\n * Maps the elements of the set to new elements.\n *\n * @example\n *\n * ```ts\n * const letters = ISet.create(['a', 'b']);\n *\n * const upper = letters.map((value) => value.toUpperCase());\n *\n * assert.deepStrictEqual(Array.from(upper), ['A', 'B']);\n * ```\n *\n * @template K2 The type of the new elements.\n * @param mapFn A function that maps an element to a new element.\n * @returns A new ISet instance with mapped elements.\n */\n map: <K2 extends MapSetKeyType>(mapFn: (key: K) => K2) => ISet<K2>;\n\n /**\n * Filters the elements of the set based on a predicate. Also supports a type\n * predicate overload that narrows the type of elements in the resulting set.\n *\n * @example\n *\n * ```ts\n * const letters = ISet.create(['apple', 'bee', 'cat']);\n *\n * const shortWords = letters.filter((value) => value.length <= 3);\n *\n * const narrowed = letters.filter(\n * (value): value is 'bee' | 'cat' => value.length === 3,\n * );\n *\n * assert.deepStrictEqual(Array.from(shortWords), ['bee', 'cat']);\n *\n * assert.deepStrictEqual(Array.from(narrowed), ['bee', 'cat']);\n * ```\n *\n * @template K2 The narrowed type of the elements.\n * @param predicate A function to test each element.\n * @returns A new ISet instance with elements that satisfy the predicate.\n */\n filter: (<K2 extends K>(predicate: (key: K) => key is K2) => ISet<K2>) &\n ((predicate: (key: K) => boolean) => ISet<K>);\n\n /**\n * Filters the elements of the set by excluding elements for which the\n * predicate returns true.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 2, 3, 4]);\n *\n * const withoutEven = numbers.filterNot((value) => value % 2 === 0);\n *\n * assert.deepStrictEqual(Array.from(withoutEven), [1, 3]);\n * ```\n *\n * @param predicate A function to test each element.\n * @returns A new ISet instance with elements for which the predicate returned\n * `false`.\n */\n filterNot: (predicate: (key: K) => boolean) => ISet<K>;\n\n // Set operations\n\n /**\n * Checks if this set is a subset of another set.\n *\n * @example\n *\n * ```ts\n * const subset = ISet.create<number>([1, 2]);\n *\n * const superset = ISet.create<number>([1, 2, 3]);\n *\n * assert.isTrue(subset.isSubsetOf(superset));\n *\n * assert.isFalse(superset.isSubsetOf(subset));\n * ```\n *\n * @param set The other set.\n * @returns `true` if this set is a subset of the other set, `false`\n * otherwise.\n */\n isSubsetOf: (set: ISet<WidenLiteral<K>>) => boolean;\n\n /**\n * Checks if this set is a superset of another set.\n *\n * @example\n *\n * ```ts\n * const superset = ISet.create<string>(['a', 'b', 'c']);\n *\n * const subset = ISet.create<string>(['a', 'c']);\n *\n * assert.isTrue(superset.isSupersetOf(subset));\n *\n * assert.isFalse(subset.isSupersetOf(superset));\n * ```\n *\n * @param set The other set.\n * @returns `true` if this set is a superset of the other set, `false`\n * otherwise.\n */\n isSupersetOf: (set: ISet<WidenLiteral<K>>) => boolean;\n\n /**\n * Returns a new set with elements that are in this set but not in another\n * set.\n *\n * @example\n *\n * ```ts\n * const all = ISet.create<number>([1, 2, 3, 4]);\n *\n * const toRemove = ISet.create<number>([2, 4]);\n *\n * const difference = all.subtract(toRemove);\n *\n * assert.deepStrictEqual(Array.from(difference), [1, 3]);\n * ```\n *\n * @param set The other set.\n * @returns A new ISet instance representing the set difference.\n */\n subtract: (set: ISet<K>) => ISet<K>;\n\n /**\n * Returns a new set with elements that are common to both this set and\n * another set.\n *\n * @example\n *\n * ```ts\n * const left = ISet.create<string>(['x', 'y']);\n *\n * const right = ISet.create<string>(['y', 'z']);\n *\n * const shared = left.intersect(right);\n *\n * assert.deepStrictEqual(Array.from(shared), ['y']);\n * ```\n *\n * @param set The other set.\n * @returns A new ISet instance representing the set intersection.\n */\n intersect: (set: ISet<K>) => ISet<K>;\n\n /**\n * Returns a new set with all elements from both this set and another set.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 2]);\n *\n * const letters = ISet.create(['a', 'b']);\n *\n * const combined = numbers.union(letters);\n *\n * assert.deepStrictEqual(Array.from(combined), [1, 2, 'a', 'b']);\n * ```\n *\n * @template K2 The type of elements in the other set.\n * @param set The other set.\n * @returns A new ISet instance representing the set union.\n */\n union: <K2 extends MapSetKeyType>(set: ISet<K2>) => ISet<K | K2>;\n\n // Side effects\n\n /**\n * Executes a callback function for each element in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['alpha', 'beta']);\n *\n * const mut_collected: string[] = [];\n *\n * set.forEach((value) => {\n * mut_collected.push(value);\n * });\n *\n * assert.deepStrictEqual(mut_collected, ['alpha', 'beta']);\n * ```\n *\n * @param callbackfn A function to execute for each element.\n */\n forEach: (callbackfn: (key: K) => void) => void;\n\n // Iterators\n\n /**\n * Returns an iterator for the elements in the set (alias for values).\n *\n * @example\n *\n * ```ts\n * const set = ISet.create([1, 2]);\n *\n * const keys = Array.from(set.keys());\n *\n * assert.deepStrictEqual(keys, [1, 2]);\n * ```\n *\n * @returns An iterable iterator of elements.\n */\n keys: () => IterableIterator<K>;\n\n /**\n * Returns an iterator for the elements in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['x', 'y']);\n *\n * const values = Array.from(set.values());\n *\n * assert.deepStrictEqual(values, ['x', 'y']);\n * ```\n *\n * @returns An iterable iterator of elements.\n */\n values: () => IterableIterator<K>;\n\n /**\n * Returns an iterator for the entries (element-element pairs) in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['red', 'blue']);\n *\n * const entries = Array.from(set.entries());\n *\n * assert.deepStrictEqual(entries, [\n * ['red', 'red'],\n * ['blue', 'blue'],\n * ]);\n * ```\n *\n * @returns An iterable iterator of entries.\n */\n entries: () => IterableIterator<readonly [K, K]>;\n\n // Conversion\n\n /**\n * Converts the elements of the set to an array.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['north', 'south']);\n *\n * assert.deepStrictEqual(set.toArray(), ['north', 'south']);\n * ```\n *\n * @returns A readonly array of elements.\n */\n toArray: () => readonly K[];\n\n /**\n * Returns the underlying readonly JavaScript Set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['alpha']);\n *\n * const raw = set.toRawSet();\n *\n * assert.isTrue(isSet(raw));\n *\n * assert.isTrue(raw.has('alpha'));\n * ```\n *\n * @returns The raw ReadonlySet instance.\n */\n toRawSet: () => ReadonlySet<K>;\n}>;\n\n/**\n * Represents an immutable set with high-performance operations and\n * comprehensive set algebra support.\n *\n * ISet is a persistent data structure that provides all the functionality of\n * JavaScript's Set while maintaining immutability. All operations that would\n * normally mutate the set instead return new ISet instances, making it safe for\n * functional programming and concurrent access.\n *\n * **Key Features:**\n *\n * - **Immutable**: All mutation operations return new instances\n * - **Set Operations**: Full support for union, intersection, difference,\n * subset/superset checks\n * - **Type Safe**: Full TypeScript support with generic element types\n * - **Iterable**: Implements standard JavaScript iteration protocols\n * - **Functional**: Rich API for map, filter, and functional composition\n *\n * **When to Use:**\n *\n * - Managing collections of unique values with immutability guarantees\n * - Set algebra operations (unions, intersections, differences)\n * - Membership testing with O(1) performance\n * - Functional programming patterns requiring immutable collections\n *\n * @template K The type of the elements in the set. Must extend MapSetKeyType.\n */\nexport type ISet<K extends MapSetKeyType> = Iterable<K> & ISetInterface<K>;\n\n/** Provides utility functions for ISet. */\nexport namespace ISet {\n /**\n * Creates a new ISet instance from an iterable of elements.\n *\n * This factory function accepts any iterable of elements, including arrays,\n * JavaScript Sets, other ISets, or custom iterables. Duplicate elements in\n * the input iterable will be automatically deduplicated in the resulting\n * set.\n *\n * **Performance:** O(n) where n is the number of elements in the iterable.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['a', 'a', 'b']);\n *\n * assert.deepStrictEqual(Array.from(set), ['a', 'b']);\n * ```\n *\n * @template K The type of the elements. Must extend MapSetKeyType.\n * @param iterable An iterable of elements (e.g., Array, Set, ISet, etc.)\n * @returns A new ISet instance containing all unique elements from the\n * iterable.\n */\n export const create = <K extends MapSetKeyType>(\n iterable: Iterable<K>,\n ): ISet<K> => new ISetClass<K>(iterable);\n\n /**\n * Checks if two ISet instances are structurally equal.\n *\n * Two ISets are considered equal if they have the same size and contain\n * exactly the same elements. The order of elements does not matter for\n * equality comparison since sets are unordered collections. Elements are\n * compared using JavaScript's `===` operator.\n *\n * **Performance:** O(n) where n is the size of the smaller set.\n *\n * @example\n *\n * ```ts\n * const first = ISet.create<number>([1, 2]);\n *\n * const second = ISet.create<number>([2, 1]);\n *\n * const third = ISet.create<number>([1, 3]);\n *\n * assert.isTrue(ISet.equal(first, second));\n *\n * assert.isFalse(ISet.equal(first, third));\n * ```\n *\n * @template K The type of the elements.\n * @param a The first ISet instance to compare.\n * @param b The second ISet instance to compare.\n * @returns `true` if the sets contain exactly the same elements, `false`\n * otherwise.\n */\n export const equal = <K extends MapSetKeyType>(\n a: ISet<K>,\n b: ISet<K>,\n ): boolean => a.size === b.size && a.every((e) => b.has(e));\n\n /**\n * Computes the difference between two ISet instances, identifying added and\n * deleted elements.\n *\n * This function performs a set difference operation to determine what\n * elements were added and what elements were deleted when transitioning from\n * the old set to the new set. This is useful for change detection, state\n * management, and synchronization scenarios.\n *\n * **Performance:** O(n + m) where n and m are the sizes of the old and new\n * sets respectively.\n *\n * @example\n *\n * ```ts\n * const previous = ISet.create<string>(['draft', 'review']);\n *\n * const current = ISet.create<string>(['review', 'published']);\n *\n * const { added, deleted } = ISet.diff(previous, current);\n *\n * assert.deepStrictEqual(Array.from(added), ['published']);\n *\n * assert.deepStrictEqual(Array.from(deleted), ['draft']);\n * ```\n *\n * @template K The type of the elements.\n * @param oldSet The original set representing the previous state.\n * @param newSet The new set representing the current state.\n * @returns An object with `added` and `deleted` properties, each containing\n * an ISet of elements that were added or removed respectively.\n */\n export const diff = <K extends MapSetKeyType>(\n oldSet: ISet<K>,\n newSet: ISet<K>,\n ): ReadonlyRecord<'added' | 'deleted', ISet<K>> =>\n ({\n deleted: oldSet.subtract(newSet),\n added: newSet.subtract(oldSet),\n }) as const;\n\n /**\n * Computes the intersection of two ISet instances.\n *\n * Returns a new set containing only the elements that are present in both\n * input sets. This operation is commutative: `intersection(a, b) ===\n * intersection(b, a)`.\n *\n * **Performance:** O(min(n, m)) where n and m are the sizes of the input\n * sets.\n *\n * @example\n *\n * ```ts\n * const left = ISet.create<number>([1, 2, 3]);\n *\n * const right = ISet.create<number>([2, 4]);\n *\n * const overlap = ISet.intersection(left, right);\n *\n * assert.deepStrictEqual(Array.from(overlap), [2]);\n * ```\n *\n * @template K The type of the elements.\n * @param a The first set.\n * @param b The second set.\n * @returns A new ISet instance containing elements common to both sets.\n */\n export const intersection = <K extends MapSetKeyType>(\n a: ISet<K>,\n b: ISet<K>,\n ): ISet<K> => a.intersect(b);\n\n /**\n * Computes the union of two ISet instances.\n *\n * Returns a new set containing all elements that are present in either input\n * set. Duplicate elements are automatically handled since sets only contain\n * unique values. This operation is commutative: `union(a, b) === union(b,\n * a)`.\n *\n * **Performance:** O(n + m) where n and m are the sizes of the input sets.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 2]);\n *\n * const words = ISet.create(['one', 'two']);\n *\n * const union = ISet.union(numbers, words);\n *\n * assert.deepStrictEqual(Array.from(union), [1, 2, 'one', 'two']);\n * ```\n *\n * @template K1 The type of elements in the first set.\n * @template K2 The type of elements in the second set.\n * @param a The first set.\n * @param b The second set.\n * @returns A new ISet instance containing all elements from both sets.\n */\n export const union = <K1 extends MapSetKeyType, K2 extends MapSetKeyType>(\n a: ISet<K1>,\n b: ISet<K2>,\n ): ISet<K1 | K2> => a.union(b);\n}\n\n/**\n * Internal class implementation for ISet providing immutable set operations.\n *\n * This class implements the ISet interface using JavaScript's native Set as the\n * underlying storage mechanism for optimal performance. All mutation operations\n * create new instances rather than modifying the existing set, ensuring\n * immutability.\n *\n * **Implementation Details:**\n *\n * - Uses ReadonlySet<K> internally for type safety and performance\n * - Implements copy-on-write semantics for efficiency\n * - Provides optional debug messaging for development\n *\n * @template K The type of the elements. Must extend MapSetKeyType.\n * @implements ISet\n * @implements Iterable\n * @internal This class should not be used directly. Use ISet.create() instead.\n */\nclass ISetClass<K extends MapSetKeyType> implements ISet<K>, Iterable<K> {\n readonly #set: ReadonlySet<K>;\n readonly #showNotFoundMessage: boolean;\n\n /**\n * Constructs an ISetClass instance with the given elements.\n *\n * @param iterable An iterable of elements to populate the set.\n * @param showNotFoundMessage Whether to log warning messages when operations\n * are performed on non-existent elements. Useful for debugging. Defaults to\n * false for production use.\n * @internal Use ISet.create() instead of calling this constructor directly.\n */\n constructor(iterable: Iterable<K>, showNotFoundMessage: boolean = false) {\n this.#set = new Set(iterable);\n\n this.#showNotFoundMessage = showNotFoundMessage;\n }\n\n /** @inheritdoc */\n get size(): SizeType.Arr {\n return asUint32(this.#set.size);\n }\n\n /** @inheritdoc */\n get isEmpty(): boolean {\n return this.size === 0;\n }\n\n /** @inheritdoc */\n has(key: K | (WidenLiteral<K> & {})): boolean {\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return this.#set.has(key as K);\n }\n\n /** @inheritdoc */\n every<L extends K>(predicate: (key: K) => key is L): this is ISet<L>;\n\n /** @inheritdoc */\n every(predicate: (key: K) => boolean): boolean;\n\n /** @inheritdoc */\n every(predicate: (key: K) => boolean): boolean {\n for (const key of this.values()) {\n if (!predicate(key)) return false;\n }\n\n return true;\n }\n\n /** @inheritdoc */\n some(predicate: (key: K) => boolean): boolean {\n for (const key of this.values()) {\n if (predicate(key)) return true;\n }\n\n return false;\n }\n\n /** @inheritdoc */\n add(key: K): ISet<K> {\n if (this.has(key)) return this;\n\n return ISet.create([...this.#set, key]);\n }\n\n /** @inheritdoc */\n delete(key: K): ISet<K> {\n if (!this.has(key)) {\n if (this.#showNotFoundMessage) {\n const keyStr = unknownToString(key);\n\n console.warn(`ISet.delete: key not found: ${keyStr}`);\n }\n\n return this;\n }\n\n return ISet.create(Array.from(this.#set).filter((k) => !Object.is(k, key)));\n }\n\n /** @inheritdoc */\n withMutations(\n actions: readonly Readonly<\n { type: 'add'; key: K } | { type: 'delete'; key: K }\n >[],\n ): ISet<K> {\n const mut_result = new Set<K>(this.#set);\n\n const updateFn = (\n action: Readonly<{ type: 'add'; key: K } | { type: 'delete'; key: K }>,\n ): void => {\n switch (action.type) {\n case 'delete':\n mut_result.delete(action.key);\n\n break;\n\n case 'add':\n mut_result.add(action.key);\n\n break;\n }\n };\n\n for (const action of actions) {\n updateFn(action);\n }\n\n return ISet.create(mut_result);\n }\n\n /** @inheritdoc */\n map<K2 extends MapSetKeyType>(mapFn: (key: K) => K2): ISet<K2> {\n return ISet.create(this.toArray().map(mapFn));\n }\n\n /** @inheritdoc */\n filter<K2 extends K>(predicate: (key: K) => key is K2): ISet<K2>;\n\n /** @inheritdoc */\n filter(predicate: (key: K) => boolean): ISet<K>;\n\n /** @inheritdoc */\n filter(predicate: (key: K) => boolean): ISet<K> {\n return ISet.create(this.toArray().filter(predicate));\n }\n\n /** @inheritdoc */\n filterNot(predicate: (key: K) => boolean): ISet<K> {\n return ISet.create(this.toArray().filter((e) => !predicate(e)));\n }\n\n /** @inheritdoc */\n forEach(callbackfn: (key: K) => void): void {\n for (const v of this.#set) {\n callbackfn(v);\n }\n }\n\n /** @inheritdoc */\n isSubsetOf(set: ISet<WidenLiteral<K>>): boolean {\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return this.every((k) => set.has(k as WidenLiteral<K>));\n }\n\n /** @inheritdoc */\n isSupersetOf(set: ISet<WidenLiteral<K>>): boolean {\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return set.every((k) => this.has(k as K));\n }\n\n /** @inheritdoc */\n subtract(set: ISet<K>): ISet<K> {\n return ISet.create(this.toArray().filter((k) => !set.has(k)));\n }\n\n /** @inheritdoc */\n intersect(set: ISet<K>): ISet<K> {\n return ISet.create(this.toArray().filter((k) => set.has(k)));\n }\n\n /** @inheritdoc */\n union<K2 extends MapSetKeyType>(set: ISet<K2>): ISet<K | K2> {\n return ISet.create([...this, ...set]);\n }\n\n /**\n * @example\n *\n * ```ts\n * const set = ISet.create(['first', 'second']);\n *\n * const collected = Array.from(set);\n *\n * assert.deepStrictEqual(collected, ['first', 'second']);\n * ```\n *\n * @inheritdoc\n */\n [Symbol.iterator](): Iterator<K> {\n return this.#set[Symbol.iterator]();\n }\n\n /** @inheritdoc */\n keys(): IterableIterator<K> {\n return this.#set.keys();\n }\n\n /** @inheritdoc */\n values(): IterableIterator<K> {\n return this.#set.values();\n }\n\n /** @inheritdoc */\n entries(): IterableIterator<readonly [K, K]> {\n return this.#set.entries();\n }\n\n /** @inheritdoc */\n toArray(): readonly K[] {\n return Array.from(this.values());\n }\n\n /** @inheritdoc */\n toRawSet(): ReadonlySet<K> {\n return this.#set;\n }\n}\n"],"names":["ISet"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmhBO,IAAU;AAAA,CAAV,CAAUA,KAAAA,KAAV;AAwBE,EAAMA,MAAA,MAAA,GAAS,CACpB,QAAA,KACY,IAAI,UAAa,QAAQ,CAAA;AAgChC,EAAMA,MAAA,KAAA,GAAQ,CACnB,CAAA,EACA,CAAA,KACY,EAAE,IAAA,KAAS,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,MAAM,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,CAAA;AAkCnD,EAAMA,KAAAA,CAAA,IAAA,GAAO,CAClB,MAAA,EACA,MAAA,MAEC;AAAA,IACC,OAAA,EAAS,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA;AAAA,IAC/B,KAAA,EAAO,MAAA,CAAO,QAAA,CAAS,MAAM;AAAA,GAC/B,CAAA;AA6BK,EAAMA,MAAA,YAAA,GAAe,CAC1B,GACA,CAAA,KACY,CAAA,CAAE,UAAU,CAAC,CAAA;AA8BpB,EAAMA,MAAA,KAAA,GAAQ,CACnB,GACA,CAAA,KACkB,CAAA,CAAE,MAAM,CAAC,CAAA;AAAA,CAAA,EAvKd,IAAA,KAAA,IAAA,GAAA,EAAA,CAAA,CAAA;AA6LjB,MAAM,SAAA,CAAmE;AAAA,EAC9D,IAAA;AAAA,EACA,oBAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,WAAA,CAAY,QAAA,EAAuB,mBAAA,GAA+B,KAAA,EAAO;AACvE,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,IAAA,IAAA,CAAK,oBAAA,GAAuB,mBAAA;AAAA,EAC9B;AAAA;AAAA,EAGA,IAAI,IAAA,GAAqB;AACvB,IAAA,OAAO,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAAA,EAChC;AAAA;AAAA,EAGA,IAAI,OAAA,GAAmB;AACrB,IAAA,OAAO,KAAK,IAAA,KAAS,CAAA;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,GAAA,EAA0C;AAE5C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,GAAQ,CAAA;AAAA,EAC/B;AAAA;AAAA,EASA,MAAM,SAAA,EAAyC;AAC7C,IAAA,KAAA,MAAW,GAAA,IAAO,IAAA,CAAK,MAAA,EAAO,EAAG;AAC/B,MAAA,IAAI,CAAC,SAAA,CAAU,GAAG,CAAA,EAAG,OAAO,KAAA;AAAA,IAC9B;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,KAAK,SAAA,EAAyC;AAC5C,IAAA,KAAA,MAAW,GAAA,IAAO,IAAA,CAAK,MAAA,EAAO,EAAG;AAC/B,MAAA,IAAI,SAAA,CAAU,GAAG,CAAA,EAAG,OAAO,IAAA;AAAA,IAC7B;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,IAAI,GAAA,EAAiB;AACnB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,IAAA;AAE1B,IAAA,OAAO,KAAK,MAAA,CAAO,CAAC,GAAG,IAAA,CAAK,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,OAAO,GAAA,EAAiB;AACtB,IAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AAClB,MAAA,IAAI,KAAK,oBAAA,EAAsB;AAC7B,QAAA,MAAM,MAAA,GAAS,gBAAgB,GAAG,CAAA;AAElC,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,4BAAA,EAA+B,MAAM,CAAA,CAAE,CAAA;AAAA,MACtD;AAEA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,KAAK,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,MAAA,CAAO,EAAA,CAAG,CAAA,EAAG,GAAG,CAAC,CAAC,CAAA;AAAA,EAC5E;AAAA;AAAA,EAGA,cACE,OAAA,EAGS;AACT,IAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAEvC,IAAA,MAAM,QAAA,GAAW,CACf,MAAA,KACS;AACT,MAAA,QAAQ,OAAO,IAAA;AAAM,QACnB,KAAK,QAAA;AACH,UAAA,UAAA,CAAW,MAAA,CAAO,OAAO,GAAG,CAAA;AAE5B,UAAA;AAAA,QAEF,KAAK,KAAA;AACH,UAAA,UAAA,CAAW,GAAA,CAAI,OAAO,GAAG,CAAA;AAEzB,UAAA;AAAA;AACJ,IACF,CAAA;AAEA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,QAAA,CAAS,MAAM,CAAA;AAAA,IACjB;AAEA,IAAA,OAAO,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA,EAC/B;AAAA;AAAA,EAGA,IAA8B,KAAA,EAAiC;AAC7D,IAAA,OAAO,KAAK,MAAA,CAAO,IAAA,CAAK,SAAQ,CAAE,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EAC9C;AAAA;AAAA,EASA,OAAO,SAAA,EAAyC;AAC9C,IAAA,OAAO,KAAK,MAAA,CAAO,IAAA,CAAK,SAAQ,CAAE,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,EACrD;AAAA;AAAA,EAGA,UAAU,SAAA,EAAyC;AACjD,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,EAAQ,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,SAAA,CAAU,CAAC,CAAC,CAAC,CAAA;AAAA,EAChE;AAAA;AAAA,EAGA,QAAQ,UAAA,EAAoC;AAC1C,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,IAAA,EAAM;AACzB,MAAA,UAAA,CAAW,CAAC,CAAA;AAAA,IACd;AAAA,EACF;AAAA;AAAA,EAGA,WAAW,GAAA,EAAqC;AAE9C,IAAA,OAAO,KAAK,KAAA,CAAM,CAAC,MAAM,GAAA,CAAI,GAAA,CAAI,CAAoB,CAAC,CAAA;AAAA,EACxD;AAAA;AAAA,EAGA,aAAa,GAAA,EAAqC;AAEhD,IAAA,OAAO,IAAI,KAAA,CAAM,CAAC,MAAM,IAAA,CAAK,GAAA,CAAI,CAAM,CAAC,CAAA;AAAA,EAC1C;AAAA;AAAA,EAGA,SAAS,GAAA,EAAuB;AAC9B,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,EAAQ,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,GAAA,CAAI,GAAA,CAAI,CAAC,CAAC,CAAC,CAAA;AAAA,EAC9D;AAAA;AAAA,EAGA,UAAU,GAAA,EAAuB;AAC/B,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,EAAQ,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,GAAA,CAAI,GAAA,CAAI,CAAC,CAAC,CAAC,CAAA;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAgC,GAAA,EAA6B;AAC3D,IAAA,OAAO,KAAK,MAAA,CAAO,CAAC,GAAG,IAAA,EAAM,GAAG,GAAG,CAAC,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,CAAC,MAAA,CAAO,QAAQ,CAAA,GAAiB;AAC/B,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,EAAE;AAAA,EACpC;AAAA;AAAA,EAGA,IAAA,GAA4B;AAC1B,IAAA,OAAO,IAAA,CAAK,KAAK,IAAA,EAAK;AAAA,EACxB;AAAA;AAAA,EAGA,MAAA,GAA8B;AAC5B,IAAA,OAAO,IAAA,CAAK,KAAK,MAAA,EAAO;AAAA,EAC1B;AAAA;AAAA,EAGA,OAAA,GAA6C;AAC3C,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,EAAQ;AAAA,EAC3B;AAAA;AAAA,EAGA,OAAA,GAAwB;AACtB,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAA;AAAA,EACjC;AAAA;AAAA,EAGA,QAAA,GAA2B;AACzB,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,EACd;AACF;;;;"}
1
+ {"version":3,"file":"iset.mjs","sources":["../../src/collections/iset.mts"],"sourcesContent":["/* eslint-disable unicorn/prefer-iterator-to-array-at-end */\nimport {\n type FixedLengthTuple,\n type ReadonlyRecord,\n type WidenLiteral,\n} from 'ts-type-forge';\nimport { asUint32 } from '../number/index.mjs';\nimport { unknownToString } from '../others/index.mjs';\nimport { type MapSetKeyType, type SizeType } from '../types.mjs';\n\n/**\n * Interface for an immutable set with membership testing and set operation\n * support.\n *\n * This interface defines all methods and properties available on ISet\n * instances. All operations that modify the set return new ISet instances,\n * preserving immutability. The underlying implementation uses JavaScript's\n * native Set but creates copies on mutations to maintain immutability.\n *\n * **Immutability Guarantees:**\n *\n * - All mutation operations (add, delete) return new ISet instances\n * - Original ISet instances are never modified\n * - Safe for concurrent access and functional programming patterns\n *\n * **Performance Characteristics:**\n *\n * - has: O(1) average case\n * - add/delete: O(n) due to copying for immutability\n * - set operations (union, intersection, difference): O(n)\n * - map/filter operations: O(n)\n * - iteration: O(n)\n *\n * @template K The type of the elements in the set. Must extend MapSetKeyType\n * (string, number, boolean, etc.)\n */\ntype ISetInterface<K extends MapSetKeyType> = Readonly<{\n // Getting information\n\n /**\n * The number of elements in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create([1, 2, 3]);\n *\n * assert.isTrue(set.size === 3);\n * ```\n */\n size: SizeType.Arr;\n\n /**\n * Checks if the set is empty.\n *\n * @example\n *\n * ```ts\n * const emptySet = ISet.create<number>([]);\n *\n * const filledSet = ISet.create([1, 2]);\n *\n * assert.isTrue(emptySet.isEmpty);\n *\n * assert.isFalse(filledSet.isEmpty);\n * ```\n */\n isEmpty: boolean;\n\n /**\n * Checks if an element exists in the set. Allows for wider literal types for\n * keys during checking.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['apple', 'banana']);\n *\n * assert.isTrue(set.has('apple'));\n *\n * assert.isFalse(set.has('cherry'));\n * ```\n *\n * @param key The element to check.\n * @returns `true` if the element exists, `false` otherwise.\n */\n has: (key: K | (WidenLiteral<K> & {})) => boolean;\n\n // Reducing a value\n\n /**\n * Checks if all elements in the set satisfy a predicate. Also supports a\n * type predicate overload that narrows the type of elements in the set if\n * the predicate returns true for all elements.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([2, 4, 6]);\n *\n * const allEven = numbers.every((value) => value % 2 === 0);\n *\n * const narrowed = numbers.every(\n * (value): value is 2 | 4 | 6 => value % 2 === 0,\n * );\n *\n * assert.isTrue(allEven);\n *\n * assert.isTrue(narrowed);\n * ```\n *\n * @template L The narrowed type of the elements.\n * @param predicate A function to test each element.\n * @returns `true` if all elements satisfy the predicate, `false` otherwise.\n */\n every: ((predicate: (key: K) => boolean) => boolean) &\n (<L extends K>(predicate: (key: K) => key is L) => this is ISet<L>);\n\n /**\n * Checks if at least one element in the set satisfies a predicate.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 3, 5]);\n *\n * assert.isTrue(numbers.some((value) => value > 4));\n *\n * assert.isFalse(numbers.some((value) => value > 10));\n * ```\n *\n * @param predicate A function to test each element.\n * @returns `true` if at least one element satisfies the predicate, `false`\n * otherwise.\n */\n some: (predicate: (key: K) => boolean) => boolean;\n\n // Mutation\n\n /**\n * Adds an element to the set.\n *\n * @example\n *\n * ```ts\n * const base = ISet.create<number>([1, 2]);\n *\n * const withThree = base.add(3);\n *\n * const unchanged = base.add(2);\n *\n * assert.deepStrictEqual(Array.from(withThree), [1, 2, 3]);\n *\n * assert.isTrue(unchanged === base);\n * ```\n *\n * @param key The element to add.\n * @returns A new ISet instance with the element added.\n */\n add: (key: K) => ISet<K>;\n\n /**\n * Deletes an element from the set.\n *\n * @example\n *\n * ```ts\n * const base = ISet.create<number>([1, 2, 3]);\n *\n * const withoutTwo = base.delete(2);\n *\n * const unchanged = base.delete(4);\n *\n * assert.deepStrictEqual(Array.from(withoutTwo), [1, 3]);\n *\n * assert.isTrue(unchanged === base);\n * ```\n *\n * @param key The element to delete.\n * @returns A new ISet instance without the specified element.\n */\n delete: (key: K) => ISet<K>;\n\n /**\n * Applies a series of mutations to the set.\n *\n * @example\n *\n * ```ts\n * const base = ISet.create<string>(['a', 'b']);\n *\n * const actions: readonly Readonly<\n * { type: 'add'; key: string } | { type: 'delete'; key: string }\n * >[] = [\n * { type: 'add', key: 'c' },\n * { type: 'delete', key: 'a' },\n * ] as const;\n *\n * const mutated = base.withMutations(actions);\n *\n * assert.deepStrictEqual(Array.from(mutated), ['b', 'c']);\n *\n * assert.deepStrictEqual(Array.from(base), ['a', 'b']);\n * ```\n *\n * @param actions An array of mutation actions (add or delete).\n * @returns A new ISet instance with all mutations applied.\n */\n withMutations: (\n actions: readonly Readonly<\n { type: 'add'; key: K } | { type: 'delete'; key: K }\n >[],\n ) => ISet<K>;\n\n // Sequence algorithms\n\n /**\n * Maps the elements of the set to new elements.\n *\n * @example\n *\n * ```ts\n * const letters = ISet.create(['a', 'b']);\n *\n * const upper = letters.map((value) => value.toUpperCase());\n *\n * assert.deepStrictEqual(Array.from(upper), ['A', 'B']);\n * ```\n *\n * @template K2 The type of the new elements.\n * @param mapFn A function that maps an element to a new element.\n * @returns A new ISet instance with mapped elements.\n */\n map: <K2 extends MapSetKeyType>(mapFn: (key: K) => K2) => ISet<K2>;\n\n /**\n * Filters the elements of the set based on a predicate. Also supports a type\n * predicate overload that narrows the type of elements in the resulting set.\n *\n * @example\n *\n * ```ts\n * const letters = ISet.create(['apple', 'bee', 'cat']);\n *\n * const shortWords = letters.filter((value) => value.length <= 3);\n *\n * const narrowed = letters.filter(\n * (value): value is 'bee' | 'cat' => value.length === 3,\n * );\n *\n * assert.deepStrictEqual(Array.from(shortWords), ['bee', 'cat']);\n *\n * assert.deepStrictEqual(Array.from(narrowed), ['bee', 'cat']);\n * ```\n *\n * @template K2 The narrowed type of the elements.\n * @param predicate A function to test each element.\n * @returns A new ISet instance with elements that satisfy the predicate.\n */\n filter: (<K2 extends K>(predicate: (key: K) => key is K2) => ISet<K2>) &\n ((predicate: (key: K) => boolean) => ISet<K>);\n\n /**\n * Filters the elements of the set by excluding elements for which the\n * predicate returns true.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 2, 3, 4]);\n *\n * const withoutEven = numbers.filterNot((value) => value % 2 === 0);\n *\n * assert.deepStrictEqual(Array.from(withoutEven), [1, 3]);\n * ```\n *\n * @param predicate A function to test each element.\n * @returns A new ISet instance with elements for which the predicate returned\n * `false`.\n */\n filterNot: (predicate: (key: K) => boolean) => ISet<K>;\n\n // Set operations\n\n /**\n * Checks if this set is a subset of another set.\n *\n * @example\n *\n * ```ts\n * const subset = ISet.create<number>([1, 2]);\n *\n * const superset = ISet.create<number>([1, 2, 3]);\n *\n * assert.isTrue(subset.isSubsetOf(superset));\n *\n * assert.isFalse(superset.isSubsetOf(subset));\n * ```\n *\n * @param set The other set.\n * @returns `true` if this set is a subset of the other set, `false`\n * otherwise.\n */\n isSubsetOf: (set: ISet<WidenLiteral<K>>) => boolean;\n\n /**\n * Checks if this set is a superset of another set.\n *\n * @example\n *\n * ```ts\n * const superset = ISet.create<string>(['a', 'b', 'c']);\n *\n * const subset = ISet.create<string>(['a', 'c']);\n *\n * assert.isTrue(superset.isSupersetOf(subset));\n *\n * assert.isFalse(subset.isSupersetOf(superset));\n * ```\n *\n * @param set The other set.\n * @returns `true` if this set is a superset of the other set, `false`\n * otherwise.\n */\n isSupersetOf: (set: ISet<WidenLiteral<K>>) => boolean;\n\n /**\n * Returns a new set with elements that are in this set but not in another\n * set.\n *\n * @example\n *\n * ```ts\n * const all = ISet.create<number>([1, 2, 3, 4]);\n *\n * const toRemove = ISet.create<number>([2, 4]);\n *\n * const difference = all.subtract(toRemove);\n *\n * assert.deepStrictEqual(Array.from(difference), [1, 3]);\n * ```\n *\n * @param set The other set.\n * @returns A new ISet instance representing the set difference.\n */\n subtract: (set: ISet<K>) => ISet<K>;\n\n /**\n * Returns a new set with elements that are common to both this set and\n * another set.\n *\n * @example\n *\n * ```ts\n * const left = ISet.create<string>(['x', 'y']);\n *\n * const right = ISet.create<string>(['y', 'z']);\n *\n * const shared = left.intersect(right);\n *\n * assert.deepStrictEqual(Array.from(shared), ['y']);\n * ```\n *\n * @param set The other set.\n * @returns A new ISet instance representing the set intersection.\n */\n intersect: (set: ISet<K>) => ISet<K>;\n\n /**\n * Returns a new set with all elements from both this set and another set.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 2]);\n *\n * const letters = ISet.create(['a', 'b']);\n *\n * const combined = numbers.union(letters);\n *\n * assert.deepStrictEqual(Array.from(combined), [1, 2, 'a', 'b']);\n * ```\n *\n * @template K2 The type of elements in the other set.\n * @param set The other set.\n * @returns A new ISet instance representing the set union.\n */\n union: <K2 extends MapSetKeyType>(set: ISet<K2>) => ISet<K | K2>;\n\n // Side effects\n\n /**\n * Executes a callback function for each element in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['alpha', 'beta']);\n *\n * const mut_collected: string[] = [];\n *\n * set.forEach((value) => {\n * mut_collected.push(value);\n * });\n *\n * assert.deepStrictEqual(mut_collected, ['alpha', 'beta']);\n * ```\n *\n * @param callbackfn A function to execute for each element.\n */\n forEach: (callbackfn: (key: K) => void) => void;\n\n // Iterators\n\n /**\n * Returns an iterator for the elements in the set (alias for values).\n *\n * @example\n *\n * ```ts\n * const set = ISet.create([1, 2]);\n *\n * const keys = Array.from(set.keys());\n *\n * assert.deepStrictEqual(keys, [1, 2]);\n * ```\n *\n * @returns An iterable iterator of elements.\n */\n keys: () => IterableIterator<K>;\n\n /**\n * Returns an iterator for the elements in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['x', 'y']);\n *\n * const values = Array.from(set.values());\n *\n * assert.deepStrictEqual(values, ['x', 'y']);\n * ```\n *\n * @returns An iterable iterator of elements.\n */\n values: () => IterableIterator<K>;\n\n /**\n * Returns an iterator for the entries (element-element pairs) in the set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['red', 'blue']);\n *\n * const entries = Array.from(set.entries());\n *\n * assert.deepStrictEqual(entries, [\n * ['red', 'red'],\n * ['blue', 'blue'],\n * ]);\n * ```\n *\n * @returns An iterable iterator of entries.\n */\n entries: () => IterableIterator<FixedLengthTuple<2, K>>;\n\n // Conversion\n\n /**\n * Converts the elements of the set to an array.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['north', 'south']);\n *\n * assert.deepStrictEqual(set.toArray(), ['north', 'south']);\n * ```\n *\n * @returns A readonly array of elements.\n */\n toArray: () => readonly K[];\n\n /**\n * Returns the underlying readonly JavaScript Set.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['alpha']);\n *\n * const raw = set.toRawSet();\n *\n * assert.isTrue(isSet(raw));\n *\n * assert.isTrue(raw.has('alpha'));\n * ```\n *\n * @returns The raw ReadonlySet instance.\n */\n toRawSet: () => ReadonlySet<K>;\n}>;\n\n/**\n * Represents an immutable set with high-performance operations and\n * comprehensive set algebra support.\n *\n * ISet is a persistent data structure that provides all the functionality of\n * JavaScript's Set while maintaining immutability. All operations that would\n * normally mutate the set instead return new ISet instances, making it safe for\n * functional programming and concurrent access.\n *\n * **Key Features:**\n *\n * - **Immutable**: All mutation operations return new instances\n * - **Set Operations**: Full support for union, intersection, difference,\n * subset/superset checks\n * - **Type Safe**: Full TypeScript support with generic element types\n * - **Iterable**: Implements standard JavaScript iteration protocols\n * - **Functional**: Rich API for map, filter, and functional composition\n *\n * **When to Use:**\n *\n * - Managing collections of unique values with immutability guarantees\n * - Set algebra operations (unions, intersections, differences)\n * - Membership testing with O(1) performance\n * - Functional programming patterns requiring immutable collections\n *\n * @template K The type of the elements in the set. Must extend MapSetKeyType.\n */\nexport type ISet<K extends MapSetKeyType> = Iterable<K> & ISetInterface<K>;\n\n/** Provides utility functions for ISet. */\nexport namespace ISet {\n /**\n * Creates a new ISet instance from an iterable of elements.\n *\n * This factory function accepts any iterable of elements, including arrays,\n * JavaScript Sets, other ISets, or custom iterables. Duplicate elements in\n * the input iterable will be automatically deduplicated in the resulting\n * set.\n *\n * **Performance:** O(n) where n is the number of elements in the iterable.\n *\n * @example\n *\n * ```ts\n * const set = ISet.create(['a', 'a', 'b']);\n *\n * assert.deepStrictEqual(Array.from(set), ['a', 'b']);\n * ```\n *\n * @template K The type of the elements. Must extend MapSetKeyType.\n * @param iterable An iterable of elements (e.g., Array, Set, ISet, etc.)\n * @returns A new ISet instance containing all unique elements from the\n * iterable.\n */\n export const create = <K extends MapSetKeyType>(\n iterable: Iterable<K>,\n ): ISet<K> => new ISetClass<K>(iterable);\n\n /**\n * Checks if two ISet instances are structurally equal.\n *\n * Two ISets are considered equal if they have the same size and contain\n * exactly the same elements. The order of elements does not matter for\n * equality comparison since sets are unordered collections. Elements are\n * compared using JavaScript's `===` operator.\n *\n * **Performance:** O(n) where n is the size of the smaller set.\n *\n * @example\n *\n * ```ts\n * const first = ISet.create<number>([1, 2]);\n *\n * const second = ISet.create<number>([2, 1]);\n *\n * const third = ISet.create<number>([1, 3]);\n *\n * assert.isTrue(ISet.equal(first, second));\n *\n * assert.isFalse(ISet.equal(first, third));\n * ```\n *\n * @template K The type of the elements.\n * @param a The first ISet instance to compare.\n * @param b The second ISet instance to compare.\n * @returns `true` if the sets contain exactly the same elements, `false`\n * otherwise.\n */\n export const equal = <K extends MapSetKeyType>(\n a: ISet<K>,\n b: ISet<K>,\n ): boolean => a.size === b.size && a.every((e) => b.has(e));\n\n /**\n * Computes the difference between two ISet instances, identifying added and\n * deleted elements.\n *\n * This function performs a set difference operation to determine what\n * elements were added and what elements were deleted when transitioning from\n * the old set to the new set. This is useful for change detection, state\n * management, and synchronization scenarios.\n *\n * **Performance:** O(n + m) where n and m are the sizes of the old and new\n * sets respectively.\n *\n * @example\n *\n * ```ts\n * const previous = ISet.create<string>(['draft', 'review']);\n *\n * const current = ISet.create<string>(['review', 'published']);\n *\n * const { added, deleted } = ISet.diff(previous, current);\n *\n * assert.deepStrictEqual(Array.from(added), ['published']);\n *\n * assert.deepStrictEqual(Array.from(deleted), ['draft']);\n * ```\n *\n * @template K The type of the elements.\n * @param oldSet The original set representing the previous state.\n * @param newSet The new set representing the current state.\n * @returns An object with `added` and `deleted` properties, each containing\n * an ISet of elements that were added or removed respectively.\n */\n export const diff = <K extends MapSetKeyType>(\n oldSet: ISet<K>,\n newSet: ISet<K>,\n ): ReadonlyRecord<'added' | 'deleted', ISet<K>> =>\n ({\n deleted: oldSet.subtract(newSet),\n added: newSet.subtract(oldSet),\n }) as const;\n\n /**\n * Computes the intersection of two ISet instances.\n *\n * Returns a new set containing only the elements that are present in both\n * input sets. This operation is commutative: `intersection(a, b) ===\n * intersection(b, a)`.\n *\n * **Performance:** O(min(n, m)) where n and m are the sizes of the input\n * sets.\n *\n * @example\n *\n * ```ts\n * const left = ISet.create<number>([1, 2, 3]);\n *\n * const right = ISet.create<number>([2, 4]);\n *\n * const overlap = ISet.intersection(left, right);\n *\n * assert.deepStrictEqual(Array.from(overlap), [2]);\n * ```\n *\n * @template K The type of the elements.\n * @param a The first set.\n * @param b The second set.\n * @returns A new ISet instance containing elements common to both sets.\n */\n export const intersection = <K extends MapSetKeyType>(\n a: ISet<K>,\n b: ISet<K>,\n ): ISet<K> => a.intersect(b);\n\n /**\n * Computes the union of two ISet instances.\n *\n * Returns a new set containing all elements that are present in either input\n * set. Duplicate elements are automatically handled since sets only contain\n * unique values. This operation is commutative: `union(a, b) === union(b,\n * a)`.\n *\n * **Performance:** O(n + m) where n and m are the sizes of the input sets.\n *\n * @example\n *\n * ```ts\n * const numbers = ISet.create([1, 2]);\n *\n * const words = ISet.create(['one', 'two']);\n *\n * const union = ISet.union(numbers, words);\n *\n * assert.deepStrictEqual(Array.from(union), [1, 2, 'one', 'two']);\n * ```\n *\n * @template K1 The type of elements in the first set.\n * @template K2 The type of elements in the second set.\n * @param a The first set.\n * @param b The second set.\n * @returns A new ISet instance containing all elements from both sets.\n */\n export const union = <K1 extends MapSetKeyType, K2 extends MapSetKeyType>(\n a: ISet<K1>,\n b: ISet<K2>,\n ): ISet<K1 | K2> => a.union(b);\n}\n\n/**\n * Internal class implementation for ISet providing immutable set operations.\n *\n * This class implements the ISet interface using JavaScript's native Set as the\n * underlying storage mechanism for optimal performance. All mutation operations\n * create new instances rather than modifying the existing set, ensuring\n * immutability.\n *\n * **Implementation Details:**\n *\n * - Uses ReadonlySet<K> internally for type safety and performance\n * - Implements copy-on-write semantics for efficiency\n * - Provides optional debug messaging for development\n *\n * @template K The type of the elements. Must extend MapSetKeyType.\n * @implements ISet\n * @implements Iterable\n * @internal This class should not be used directly. Use ISet.create() instead.\n */\nclass ISetClass<K extends MapSetKeyType> implements ISet<K>, Iterable<K> {\n readonly #set: ReadonlySet<K>;\n readonly #showNotFoundMessage: boolean;\n\n /**\n * Constructs an ISetClass instance with the given elements.\n *\n * @param iterable An iterable of elements to populate the set.\n * @param showNotFoundMessage Whether to log warning messages when operations\n * are performed on non-existent elements. Useful for debugging. Defaults to\n * false for production use.\n * @internal Use ISet.create() instead of calling this constructor directly.\n */\n constructor(iterable: Iterable<K>, showNotFoundMessage: boolean = false) {\n this.#set = new Set(iterable);\n\n this.#showNotFoundMessage = showNotFoundMessage;\n }\n\n /** @inheritdoc */\n get size(): SizeType.Arr {\n return asUint32(this.#set.size);\n }\n\n /** @inheritdoc */\n get isEmpty(): boolean {\n return this.size === 0;\n }\n\n /** @inheritdoc */\n has(key: K | (WidenLiteral<K> & {})): boolean {\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return this.#set.has(key as K);\n }\n\n /** @inheritdoc */\n every<L extends K>(predicate: (key: K) => key is L): this is ISet<L>;\n\n /** @inheritdoc */\n every(predicate: (key: K) => boolean): boolean;\n\n /** @inheritdoc */\n every(predicate: (key: K) => boolean): boolean {\n for (const key of this.values()) {\n if (!predicate(key)) return false;\n }\n\n return true;\n }\n\n /** @inheritdoc */\n some(predicate: (key: K) => boolean): boolean {\n for (const key of this.values()) {\n if (predicate(key)) return true;\n }\n\n return false;\n }\n\n /** @inheritdoc */\n add(key: K): ISet<K> {\n if (this.has(key)) return this;\n\n return ISet.create([...this.#set, key]);\n }\n\n /** @inheritdoc */\n delete(key: K): ISet<K> {\n if (!this.has(key)) {\n if (this.#showNotFoundMessage) {\n const keyStr = unknownToString(key);\n\n console.warn(`ISet.delete: key not found: ${keyStr}`);\n }\n\n return this;\n }\n\n return ISet.create(Array.from(this.#set).filter((k) => !Object.is(k, key)));\n }\n\n /** @inheritdoc */\n withMutations(\n actions: readonly Readonly<\n { type: 'add'; key: K } | { type: 'delete'; key: K }\n >[],\n ): ISet<K> {\n const mut_result = new Set<K>(this.#set);\n\n const updateFn = (\n action: Readonly<{ type: 'add'; key: K } | { type: 'delete'; key: K }>,\n ): void => {\n switch (action.type) {\n case 'delete':\n mut_result.delete(action.key);\n\n break;\n\n case 'add':\n mut_result.add(action.key);\n\n break;\n }\n };\n\n for (const action of actions) {\n updateFn(action);\n }\n\n return ISet.create(mut_result);\n }\n\n /** @inheritdoc */\n map<K2 extends MapSetKeyType>(mapFn: (key: K) => K2): ISet<K2> {\n return ISet.create(this.toArray().map(mapFn));\n }\n\n /** @inheritdoc */\n filter<K2 extends K>(predicate: (key: K) => key is K2): ISet<K2>;\n\n /** @inheritdoc */\n filter(predicate: (key: K) => boolean): ISet<K>;\n\n /** @inheritdoc */\n filter(predicate: (key: K) => boolean): ISet<K> {\n return ISet.create(this.toArray().filter(predicate));\n }\n\n /** @inheritdoc */\n filterNot(predicate: (key: K) => boolean): ISet<K> {\n return ISet.create(this.toArray().filter((e) => !predicate(e)));\n }\n\n /** @inheritdoc */\n forEach(callbackfn: (key: K) => void): void {\n for (const v of this.#set) {\n callbackfn(v);\n }\n }\n\n /** @inheritdoc */\n isSubsetOf(set: ISet<WidenLiteral<K>>): boolean {\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return this.every((k) => set.has(k as WidenLiteral<K>));\n }\n\n /** @inheritdoc */\n isSupersetOf(set: ISet<WidenLiteral<K>>): boolean {\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return set.every((k) => this.has(k as K));\n }\n\n /** @inheritdoc */\n subtract(set: ISet<K>): ISet<K> {\n return ISet.create(this.toArray().filter((k) => !set.has(k)));\n }\n\n /** @inheritdoc */\n intersect(set: ISet<K>): ISet<K> {\n return ISet.create(this.toArray().filter((k) => set.has(k)));\n }\n\n /** @inheritdoc */\n union<K2 extends MapSetKeyType>(set: ISet<K2>): ISet<K | K2> {\n return ISet.create([...this, ...set]);\n }\n\n /**\n * @example\n *\n * ```ts\n * const set = ISet.create(['first', 'second']);\n *\n * const collected = Array.from(set);\n *\n * assert.deepStrictEqual(collected, ['first', 'second']);\n * ```\n *\n * @inheritdoc\n */\n [Symbol.iterator](): Iterator<K> {\n return this.#set[Symbol.iterator]();\n }\n\n /** @inheritdoc */\n keys(): IterableIterator<K> {\n return this.#set.keys();\n }\n\n /** @inheritdoc */\n values(): IterableIterator<K> {\n return this.#set.values();\n }\n\n /** @inheritdoc */\n entries(): IterableIterator<FixedLengthTuple<2, K>> {\n return this.#set.entries();\n }\n\n /** @inheritdoc */\n toArray(): readonly K[] {\n return Array.from(this.values());\n }\n\n /** @inheritdoc */\n toRawSet(): ReadonlySet<K> {\n return this.#set;\n }\n}\n"],"names":["ISet"],"mappings":"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"}
@@ -27,7 +27,7 @@ type Level = 'finite' | 'int' | 'number' | 'safeint';
27
27
  export type SignOf<N> = [N] extends [PositiveNumber] ? 'pos' : [N] extends [NegativeNumber] ? 'neg' : [N] extends [NonNegativeNumber] ? 'nonneg' : [N] extends [NonPositiveNumber] ? 'nonpos' : [N] extends [NonZeroNumber] ? 'nonzero' : 'any';
28
28
  /** Classifies a numeric type's level. */
29
29
  export type LevelOf<N> = [N] extends [SafeInt] ? 'safeint' : [N] extends [Int] ? 'int' : [N] extends [FiniteNumber] ? 'finite' : 'number';
30
- type And<A extends boolean, B extends boolean> = [A, B] extends [true, true] ? true : false;
30
+ type And<A extends boolean, B extends boolean> = [A] extends [true] ? [B] extends [true] ? true : false : false;
31
31
  type Or<A extends boolean, B extends boolean> = true extends A | B ? true : false;
32
32
  /** Whether the value is guaranteed `>= 0`. */
33
33
  type Ge0<S extends Sign> = S extends 'pos' | 'nonneg' ? true : false;
@@ -54,7 +54,7 @@ type AddMulLevel<LA extends Level, LB extends Level> = LooserLevel<LA, LB> exten
54
54
  /** Exact division yields a (possibly fractional) finite number. */
55
55
  type DivLevel<LA extends Level, LB extends Level> = 'number' extends LA | LB ? 'number' : 'finite';
56
56
  /** Floor division yields an integer; the safe range is preserved. */
57
- type DivIntLevel<LA extends Level, LB extends Level> = 'number' extends LA | LB ? 'number' : [LA, LB] extends ['safeint', 'safeint'] ? 'safeint' : 'int';
57
+ type DivIntLevel<LA extends Level, LB extends Level> = 'number' extends LA | LB ? 'number' : [LA] extends ['safeint'] ? [LB] extends ['safeint'] ? 'safeint' : 'int' : 'int';
58
58
  type ReconstructNumber<S extends Sign> = S extends 'pos' ? PositiveNumber : S extends 'neg' ? NegativeNumber : S extends 'nonneg' ? NonNegativeNumber : S extends 'nonpos' ? NonPositiveNumber : S extends 'nonzero' ? NonZeroNumber : number;
59
59
  type ReconstructFinite<S extends Sign> = S extends 'pos' ? PositiveFiniteNumber : S extends 'neg' ? NegativeFiniteNumber : S extends 'nonneg' ? NonNegativeFiniteNumber : S extends 'nonpos' ? NonPositiveFiniteNumber : S extends 'nonzero' ? NonZeroFiniteNumber : FiniteNumber;
60
60
  type ReconstructInt<S extends Sign> = S extends 'pos' ? PositiveInt : S extends 'neg' ? NegativeInt : S extends 'nonneg' ? Uint : S extends 'nonpos' ? NonPositiveInt : S extends 'nonzero' ? NonZeroInt : Int;
@@ -1 +1 @@
1
- {"version":3,"file":"num-arithmetic-types.d.mts","sourceRoot":"","sources":["../../src/number/num-arithmetic-types.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"num-arithmetic-types.d.mts","sourceRoot":"","sources":["../../src/number/num-arithmetic-types.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-data-forge",
3
- "version": "14.0.0",
3
+ "version": "14.0.1",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript",
@@ -36,15 +36,15 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "@sindresorhus/is": "^8.1.0",
39
- "ts-type-forge": "^9.1.1"
39
+ "ts-type-forge": "~9.1.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@emotion/react": "11.14.0",
43
43
  "@emotion/styled": "11.14.1",
44
44
  "@mui/material": "9.2.0",
45
- "@types/react": "19.2.17",
45
+ "@types/react": "19.2.18",
46
46
  "immer": "11.1.15",
47
- "react": "19.2.7",
47
+ "react": "19.2.8",
48
48
  "typedoc": "0.28.20",
49
49
  "typedoc-github-theme": "0.4.0"
50
50
  },
@@ -85,7 +85,6 @@
85
85
  "tsc": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
86
86
  "tscw": "node ../../node_modules/typescript-native/bin/tsc --noEmit --watch -p ./tsconfig.json",
87
87
  "type-check": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
88
- "update-packages": "pnpm update --latest",
89
88
  "z:prettier": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --ignore-path ../../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --write",
90
89
  "z:vitest": "vitest --config ./configs/vitest.config.mts",
91
90
  "z:vitest:node": "pnpm run z:vitest --project='Node.js'"
@@ -1,4 +1,9 @@
1
- import { type SafeInt, type SafeUint, type SmallUint } from 'ts-type-forge';
1
+ import {
2
+ type FixedLengthTuple,
3
+ type SafeInt,
4
+ type SafeUint,
5
+ type SmallUint,
6
+ } from 'ts-type-forge';
2
7
  import { expectType } from '../../expect-type.mjs';
3
8
  import { range as rangeIterator } from '../../iterator/index.mjs';
4
9
  import {
@@ -24,7 +29,7 @@ describe('Arr creations', () => {
24
29
  test('fixed length', () => {
25
30
  const result = zeros(3);
26
31
 
27
- expectType<typeof result, readonly [0, 0, 0]>('=');
32
+ expectType<typeof result, FixedLengthTuple<3, 0>>('=');
28
33
 
29
34
  assert.deepStrictEqual(result, [0, 0, 0]);
30
35
  });
@@ -125,7 +130,7 @@ describe('Arr creations', () => {
125
130
  test('fixed length with primitive value', () => {
126
131
  const result = create(3, 'a');
127
132
 
128
- expectType<typeof result, readonly ['a', 'a', 'a']>('=');
133
+ expectType<typeof result, FixedLengthTuple<3, 'a'>>('=');
129
134
 
130
135
  assert.deepStrictEqual(result, ['a', 'a', 'a']);
131
136
  });
@@ -133,7 +138,7 @@ describe('Arr creations', () => {
133
138
  test('fixed length with null', () => {
134
139
  const result = create(2, null);
135
140
 
136
- expectType<typeof result, readonly [null, null]>('=');
141
+ expectType<typeof result, FixedLengthTuple<2, null>>('=');
137
142
 
138
143
  assert.deepStrictEqual(result, [null, null]);
139
144
  });
@@ -144,10 +149,7 @@ describe('Arr creations', () => {
144
149
  const result = create(2, obj);
145
150
 
146
151
  // transformer-ignore-next-line
147
- expectType<
148
- typeof result,
149
- readonly [Readonly<{ id: 1 }>, Readonly<{ id: 1 }>]
150
- >('~=');
152
+ expectType<typeof result, FixedLengthTuple<2, Readonly<{ id: 1 }>>>('~=');
151
153
 
152
154
  assert.deepStrictEqual(result, [obj, obj]);
153
155
 
@@ -88,7 +88,7 @@ describe('map preserves length constraints', () => {
88
88
  test('a plain tuple still maps element-wise', () => {
89
89
  const result = map([1, 2, 3] as const, String);
90
90
 
91
- expectType<typeof result, readonly [string, string, string]>('=');
91
+ expectType<typeof result, FixedLengthTuple<3, string>>('=');
92
92
 
93
93
  assert.deepStrictEqual(result, ['1', '2', '3']);
94
94
  });
@@ -268,7 +268,7 @@ describe('creation utilities report an exact length past their tuple range', ()
268
268
  test('a length still inside the tuple range keeps its exact tuple type', () => {
269
269
  const result = create(3, 'x');
270
270
 
271
- expectType<typeof result, readonly ['x', 'x', 'x']>('=');
271
+ expectType<typeof result, FixedLengthTuple<3, 'x'>>('=');
272
272
 
273
273
  assert.deepStrictEqual(result, ['x', 'x', 'x']);
274
274
  });
@@ -2,11 +2,10 @@ import {
2
2
  type ChangeArrayElement,
3
3
  type ConstrainedList,
4
4
  type FixedLengthTuple,
5
- type HasLengthConstraint,
6
5
  type Increment,
7
6
  type IsFixedLengthList,
8
7
  type NonEmptyArray,
9
- type NonEmptyTuple,
8
+ type UnknownBrand,
10
9
  } from 'ts-type-forge';
11
10
  import { asPositiveUint32 } from '../../number/index.mjs';
12
11
  import { castMutable } from '../../others/index.mjs';
@@ -356,29 +355,33 @@ const toUnshiftedImpl = <Ar extends readonly unknown[], const V>(
356
355
  * assert.deepStrictEqual(filledCurried, ['x', 'x', 'x']);
357
356
  * ```
358
357
  */
358
+ export function toFilled<
359
+ const Ar extends readonly unknown[] & UnknownBrand,
360
+ const V,
361
+ >(array: Ar, value: V): ChangeArrayElement<Ar, V>;
362
+
363
+ // For an array or tuple that carries no length brand the homomorphic mapping
364
+ // already covers every case the conditional spelled out — a fixed-length tuple
365
+ // keeps its length, `readonly [A, ...A[]]` stays non-empty, and `readonly A[]`
366
+ // stays unbounded. Stating it directly is what keeps this usable from a
367
+ // caller that is itself generic over the array: a conditional a *generic* `Ar`
368
+ // cannot decide stays deferred, and its branded branch is then not assignable
369
+ // to the caller's own mapping.
359
370
  export function toFilled<const Ar extends readonly unknown[], const V>(
360
371
  array: Ar,
361
372
  value: V,
362
- ): HasLengthConstraint<Ar> extends true
363
- ? ChangeArrayElement<Ar, V>
364
- : IsFixedLengthList<Ar> extends true
365
- ? FixedLengthTuple<Ar['length'], V>
366
- : Ar extends NonEmptyTuple<unknown>
367
- ? NonEmptyArray<V>
368
- : readonly V[];
373
+ ): Readonly<{ [K in keyof Ar]: V }>;
369
374
 
370
- // curried version
375
+ // curried version — the two cases have to be overloads of the *returned*
376
+ // function, spelled as an intersection of function types (see `Arr.map`).
371
377
  export function toFilled<const V>(
372
378
  value: V,
373
- ): <const Ar extends readonly unknown[]>(
379
+ ): (<const Ar extends readonly unknown[] & UnknownBrand>(
374
380
  array: Ar,
375
- ) => HasLengthConstraint<Ar> extends true
376
- ? ChangeArrayElement<Ar, V>
377
- : IsFixedLengthList<Ar> extends true
378
- ? FixedLengthTuple<Ar['length'], V>
379
- : Ar extends NonEmptyTuple<unknown>
380
- ? NonEmptyArray<V>
381
- : readonly V[];
381
+ ) => ChangeArrayElement<Ar, V>) &
382
+ (<const Ar extends readonly unknown[]>(
383
+ array: Ar,
384
+ ) => Readonly<{ [K in keyof Ar]: V }>);
382
385
 
383
386
  export function toFilled<E>(
384
387
  ...args: readonly [array: readonly E[], value: E] | readonly [value: E]
@@ -412,6 +415,20 @@ const toFilledImpl = <E,>(array: readonly E[], value: E): readonly E[] =>
412
415
  * assert.deepStrictEqual(filledPrefix, [8, 8, 2, 3, 4]);
413
416
  * ```
414
417
  */
418
+ export function toRangeFilled<
419
+ const Ar extends readonly unknown[] & UnknownBrand,
420
+ const V,
421
+ >(
422
+ array: Ar,
423
+ value: V,
424
+ fillRange: readonly [
425
+ start: ArgArrayIndexWithNegative<Ar>,
426
+ end: ArgArrayIndexWithNegative<Ar>,
427
+ ],
428
+ ): ChangeArrayElement<Ar, V | Ar[number]>;
429
+
430
+ // See `toFilled` for why the unbranded case states the homomorphic mapping
431
+ // directly instead of going through a conditional.
415
432
  export function toRangeFilled<const Ar extends readonly unknown[], const V>(
416
433
  array: Ar,
417
434
  value: V,
@@ -419,13 +436,7 @@ export function toRangeFilled<const Ar extends readonly unknown[], const V>(
419
436
  start: ArgArrayIndexWithNegative<Ar>,
420
437
  end: ArgArrayIndexWithNegative<Ar>,
421
438
  ],
422
- ): HasLengthConstraint<Ar> extends true
423
- ? ChangeArrayElement<Ar, V | Ar[number]>
424
- : IsFixedLengthList<Ar> extends true
425
- ? FixedLengthTuple<Ar['length'], V | Ar[number]>
426
- : Ar extends NonEmptyTuple<unknown>
427
- ? NonEmptyArray<V | Ar[number]>
428
- : readonly (V | Ar[number])[];
439
+ ): Readonly<{ [K in keyof Ar]: V | Ar[number] }>;
429
440
 
430
441
  // curried version
431
442
  export function toRangeFilled<const V>(
@@ -434,15 +445,12 @@ export function toRangeFilled<const V>(
434
445
  start: SizeType.ArgArrWithNegative,
435
446
  end: SizeType.ArgArrWithNegative,
436
447
  ],
437
- ): <const Ar extends readonly unknown[]>(
448
+ ): (<const Ar extends readonly unknown[] & UnknownBrand>(
438
449
  array: Ar,
439
- ) => HasLengthConstraint<Ar> extends true
440
- ? ChangeArrayElement<Ar, V | Ar[number]>
441
- : IsFixedLengthList<Ar> extends true
442
- ? FixedLengthTuple<Ar['length'], V | Ar[number]>
443
- : Ar extends NonEmptyTuple<unknown>
444
- ? NonEmptyArray<V | Ar[number]>
445
- : readonly (V | Ar[number])[];
450
+ ) => ChangeArrayElement<Ar, V | Ar[number]>) &
451
+ (<const Ar extends readonly unknown[]>(
452
+ array: Ar,
453
+ ) => Readonly<{ [K in keyof Ar]: V | Ar[number] }>);
446
454
 
447
455
  export function toRangeFilled<E, const V>(
448
456
  ...args:
@@ -8,6 +8,7 @@ import {
8
8
  import { expectType } from '../../expect-type.mjs';
9
9
  import { asUint32 } from '../../number/index.mjs';
10
10
  import { type SizeType } from '../../types.mjs';
11
+ import { asMinLengthArray } from './array-utils-length-bounded-array-cast.mjs';
11
12
  import {
12
13
  set,
13
14
  toFilled,
@@ -243,6 +244,45 @@ describe('Arr modifications', () => {
243
244
 
244
245
  assert.deepStrictEqual(result, [0, 0, 0]);
245
246
  });
247
+
248
+ test('should preserve the tuple shape under a generic parameter', () => {
249
+ // A caller that is itself generic over the tuple cannot resolve a
250
+ // conditional return type, so the unbranded overload has to state the
251
+ // homomorphic mapping directly.
252
+ const blank = <const T extends readonly number[]>(
253
+ xs: T,
254
+ ): Readonly<{ [K in keyof T]: 0 }> => toFilled(xs, 0);
255
+
256
+ const result = blank([1, 2, 3] as const);
257
+
258
+ expectType<typeof result, FixedLengthTuple<3, 0>>('=');
259
+
260
+ assert.deepStrictEqual<FixedLengthTuple<3, 0>>(result, [0, 0, 0]);
261
+ });
262
+
263
+ test('should preserve the tuple shape under a generic parameter when curried', () => {
264
+ const blank = <const T extends readonly number[]>(
265
+ xs: T,
266
+ ): Readonly<{ [K in keyof T]: 0 }> => toFilled(0)(xs);
267
+
268
+ const result = blank([1, 2] as const);
269
+
270
+ expectType<typeof result, FixedLengthTuple<2, 0>>('=');
271
+
272
+ assert.deepStrictEqual<FixedLengthTuple<2, 0>>(result, [0, 0]);
273
+ });
274
+
275
+ test('should keep the length brand of a branded array', () => {
276
+ const lower: MinLengthArray<2, number> = asMinLengthArray(2, [1, 2, 3]);
277
+
278
+ const filled = toFilled(lower, 0);
279
+
280
+ expectType<typeof filled, MinLengthArray<2, 0>>('~=');
281
+
282
+ // The brand is not part of the runtime value, so compare structurally —
283
+ // the type argument is what widens it, no intermediate binding needed.
284
+ assert.deepStrictEqual<readonly number[]>(filled, [0, 0, 0]);
285
+ });
246
286
  });
247
287
 
248
288
  describe(toRangeFilled, () => {
@@ -270,6 +310,18 @@ describe('Arr modifications', () => {
270
310
  assert.deepStrictEqual(result, [1, 2, 3]);
271
311
  });
272
312
 
313
+ test('should preserve the tuple shape under a generic parameter', () => {
314
+ const blankMiddle = <const T extends readonly number[]>(
315
+ xs: T,
316
+ ): Readonly<{ [K in keyof T]: number }> => toRangeFilled(xs, 0, [1, 2]);
317
+
318
+ const result = blankMiddle([1, 2, 3] as const);
319
+
320
+ expectType<typeof result, FixedLengthTuple<3, number>>('=');
321
+
322
+ assert.deepStrictEqual<FixedLengthTuple<3, number>>(result, [1, 0, 3]);
323
+ });
324
+
273
325
  test('should clamp range to array bounds', () => {
274
326
  const arr = [1, 2, 3] as readonly number[];
275
327