UNPKG

swisslist

Version:

A functional, immutable list implementation with a rich set of methods for manipulating collections.

885 lines 22.7 kB
//#region src/index.d.ts /** * A functional, immutable list implementation that provides a rich set of methods for manipulating collections. * The List class is designed to be chainable and immutable, meaning each operation returns a new List instance * rather than modifying the existing one. * * @example * ```ts * // Create a new list * const list = List.of(1, 2, 3); * * // Chain operations * const result = list * .map(x => x * 2) * .filter(x => x > 4) * .reverse(); * ``` */ declare class List<T> implements Iterable<T> { private readonly internal; private constructor(); [Symbol.iterator](): Iterator<T>; /** * Checks if a value is an instance of List. * * @example * ```ts * List.isList(List.of(1, 2, 3)); // true * List.isList([]); // false * List.isList(null); // false * ``` */ static isList(value: unknown): value is List<unknown>; /** * Creates an empty List. * * @example * ```ts * const empty = List.empty(); * empty.size; // 0 * ``` */ static empty<T>(): List<T>; /** * Creates a new List from the given items. * * @example * ```ts * const list = List.of(1, 2, 3); * list.size; // 3 * ``` */ static of<T>(...items: readonly T[]): List<T>; /** * Creates a new List from an iterable or array-like object. * * @example * ```ts * const list1 = List.from([1, 2, 3]); * const list2 = List.from(new Set([1, 2, 3])); * const list3 = List.from('hello'); // ['h', 'e', 'l', 'l', 'o'] * ``` */ static from<T>(iterable: Iterable<T> | ArrayLike<T>): List<T>; /** * Creates a List of numbers from start to end (inclusive) with optional step. * * @example * ```ts * List.range(1, 5); // [1, 2, 3, 4, 5] * List.range(0, 10, 2); // [0, 2, 4, 6, 8, 10] * List.range(5, 1, -1); // [5, 4, 3, 2, 1] * ``` */ static range(from: number, to: number, step?: number): List<number>; /** * Returns the number of items in the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.size; // 3 * ``` */ get size(): number; /** * Resolves negative indices to positive, e.g., -1 means last item */ private resolveIndex; /** * Returns true if the resolved index is out of bounds */ private isOutOfBounds; /** * Checks if the given index corresponds to the first element in the List. * Does not resolve negative indices. * * @example * ```ts * const list = List.of(1, 2, 3); * list.isFirst(0); // true * list.isFirst(1); // false * list.isFirst(-1); // false * ``` */ isFirst(index: number): boolean; /** * Checks if the given index corresponds to the last element in the List. * Does not resolve negative indices. * * @example * ```ts * const list = List.of(1, 2, 3); * list.isLast(2); // true * list.isLast(1); // false * list.isLast(-1); // false * ``` */ isLast(index: number): boolean; /** * Appends items to the end of the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.append(4, 5); // [1, 2, 3, 4, 5] * ``` */ append(...items: readonly T[]): List<T>; /** * Returns the item at the specified index. Supports negative indices. * * @example * ```ts * const list = List.of(1, 2, 3); * list.at(0); // 1 * list.at(-1); // 3 * list.at(5); // undefined * ``` */ at(index: number): T | undefined; /** * Splits the List into chunks of the specified size. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.chunk(2); // [[1, 2], [3, 4], [5]] * ``` */ chunk(size: number): List<List<T>>; /** * Creates a shallow or deep copy of the List. * * @example * ```ts * const list = List.of({ id: 1 }, { id: 2 }); * const shallow = list.clone(); * const deep = list.clone(true); * ``` */ clone(deep?: boolean): List<T>; /** * Removes null and undefined values from the List. * * @example * ```ts * const list = List.of(1, null, 2, undefined, 3); * list.compact(); // [1, 2, 3] * ``` */ compact(): List<NonNullable<T>>; /** * Maps over the List and filters out null and undefined values. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.compactMap(x => x % 2 === 0 ? x * 2 : null); // [4, 8] * ``` */ compactMap<U>(fn: (item: T) => U | null | undefined): List<U>; /** * Concatenates two Lists. * * @example * ```ts * const list1 = List.of(1, 2); * const list2 = List.of(3, 4); * list1.concat(list2); // [1, 2, 3, 4] * ``` */ concat(list: List<T>): List<T>; /** * Groups items by a key and counts occurrences. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.countBy(x => x % 2 === 0 ? 'even' : 'odd'); * // { even: 2, odd: 3 } * ``` */ countBy<K extends string>(fn: (item: T) => K): Partial<Record<K, number>>; /** * Returns items that are in this List but not in the other List. * * @example * ```ts * const list1 = List.of(1, 2, 3, 4); * const list2 = List.of(3, 4, 5, 6); * list1.difference(list2); // [1, 2] * ``` */ difference(list: List<T>): List<T>; /** * Returns items that are in this List but not in the other List, using a key function. * * @example * ```ts * const list1 = List.of({ id: 1 }, { id: 2 }, { id: 3 }); * const list2 = List.of({ id: 2 }, { id: 3 }, { id: 4 }); * list1.differenceBy(list2, x => x.id); // [{ id: 1 }] * ``` */ differenceBy<K>(list: List<T>, fn: (item: T) => K): List<T>; /** * Removes the first n items from the List. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.drop(2); // [3, 4, 5] * ``` */ drop(n: number): List<T>; /** * Removes the first item from the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.dropFirst(); // [2, 3] * ``` */ dropFirst(): List<T>; /** * Removes the last n items from the List. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.dropLast(2); // [1, 2, 3] * ``` */ dropLast(n: number): List<T>; /** * Removes items from the start of the List while the predicate is true. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.dropWhile(x => x < 3); // [3, 4, 5] * ``` */ dropWhile(fn: (item: T) => boolean): List<T>; /** * Executes a function for each item in the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.each((item, index) => console.log(item, index)); * ``` */ each(fn: (item: T, index: number) => void): this; /** * Returns a List of [index, item] pairs. * * @example * ```ts * const list = List.of('a', 'b', 'c'); * list.enumerate(); // [[0, 'a'], [1, 'b'], [2, 'c']] * ``` */ enumerate(): List<[number, T]>; /** * Tests if all items in the List satisfy the predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.every(x => x > 0); // true * list.every(x => x > 2); // false * ``` */ every<U extends T>(fn: (item: T, index: number) => item is U): this is List<U>; every(fn: (item: T, index: number) => boolean): boolean; /** * Returns a new List with items that satisfy the predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.filter(x => x % 2 === 0); // [2, 4] * ``` */ filter<U extends T>(fn: (item: T, index: number) => item is U): List<U>; filter(fn: (item: T, index: number) => boolean): List<T>; /** * Returns the first item that satisfies the predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.find(x => x > 3); // 4 * ``` */ find(fn: (item: T) => boolean): T | undefined; /** * Returns the index of the first item that satisfies the predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.findIndex(x => x > 3); // 3 * ``` */ findIndex(fn: (item: T) => boolean): number | undefined; /** * Returns the last item that satisfies the predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.findLast(x => x < 4); // 3 * ``` * @note Uses Array.prototype.findLast, which requires ES2022 or later. */ findLast(fn: (item: T) => boolean): T | undefined; /** * Returns the index of the last item that satisfies the predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.findLastIndex(x => x < 4); // 2 * ``` * @note Uses Array.prototype.findLastIndex, which requires ES2022 or later. */ findLastIndex(fn: (item: T) => boolean): number | undefined; /** * Returns the first item in the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.first(); // 1 * ``` */ first(): T | undefined; /** * Flattens the List to the specified depth. * * @example * ```ts * const list = List.from([1, [2, 3], [4, [5]]]); * list.flat(1); // [1, 2, 3, 4, [5]] * list.flat(2); // [1, 2, 3, 4, 5] * ``` */ flat<D extends number>(depth?: D): List<FlatArray<readonly T[], D>>; /** * Maps over the List and flattens the result. * * @example * ```ts * const list = List.of(1, 2, 3); * list.flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6] * ``` */ flatMap<U>(fn: (item: T) => U | U[]): List<U>; /** * Groups items by a key function. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.groupBy(x => x % 2 === 0 ? 'even' : 'odd'); * // { even: [2, 4], odd: [1, 3, 5] } * ``` */ groupBy<K extends string>(fn: (item: T) => K): Partial<Record<K, List<T>>>; /** * Checks if an item exists in the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.has(2); // true * list.has(4); // false * ``` */ has(item: T): boolean; /** * Inserts items at the specified index. * * @example * ```ts * const list = List.of(1, 2, 3); * list.insertAt(1, 4, 5); // [1, 4, 5, 2, 3] * ``` */ insertAt(index: number, ...items: readonly T[]): List<T>; /** * Returns items that exist in both Lists. * * @example * ```ts * const list1 = List.of(1, 2, 3); * const list2 = List.of(2, 3, 4); * list1.intersect(list2); // [2, 3] * ``` */ intersect(other: List<T>): List<T>; /** * Returns items that exist in both Lists, using a key function. * * @example * ```ts * const list1 = List.of({ id: 1 }, { id: 2 }, { id: 3 }); * const list2 = List.of({ id: 2 }, { id: 3 }, { id: 4 }); * list1.intersectBy(list2, x => x.id); // [{ id: 2 }, { id: 3 }] * ``` */ intersectBy<K>(other: List<T>, fn: (item: T) => K): List<T>; /** * Checks if the List is empty. * * @example * ```ts * List.empty().isEmpty(); // true * List.of(1).isEmpty(); // false * ``` */ isEmpty(): boolean; /** * Returns the last item in the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.last(); // 3 * ``` */ last(): T | undefined; /** * Maps over the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.map(x => x * 2); // [2, 4, 6] * ``` */ map<U>(fn: (item: T, index: number) => U): List<U>; move(from: number, to: number): List<T>; /** * Partitions the List into two Lists based on a predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * const [even, odd] = list.partition(x => x % 2 === 0); * // even: [2, 4] * // odd: [1, 3, 5] * ``` */ partition<U extends T>(fn: (item: T) => item is U): [List<U>, List<Exclude<T, U>>]; partition(fn: (item: T) => boolean): [List<T>, List<T>]; /** * Prepends items to the start of the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.prepend(0, -1); // [-1, 0, 1, 2, 3] * ``` */ prepend(...items: readonly T[]): List<T>; /** * Returns a random item from the List. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.random(); // random item from the list * ``` * @note For an empty list, returns undefined. */ random(): T | undefined; /** * Reduces the List to a single value. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.reduce(0, (acc, x) => acc + x); // 10 * ``` */ reduce<U>(initialValue: U, fn: (acc: U, item: T) => U): U; /** * Reduces the List from right to left. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.reduceRight('', (acc, x) => acc + x); // '4321' * ``` */ reduceRight<U>(initialValue: U, fn: (acc: U, item: T) => U): U; /** * Removes an item at the specified index. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.removeAt(1); // [1, 3, 4] * ``` */ removeAt(index: number): List<T>; /** * Replaces an item at the specified index. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.replaceAt(1, 5); // [1, 5, 3, 4] * ``` */ replaceAt(index: number, item: T): List<T>; /** * Reverses the List. * * @example * ```ts * const list = List.of(1, 2, 3); * list.reverse(); // [3, 2, 1] * ``` */ reverse(): List<T>; /** * Rotates the List by n positions. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.rotate(2); // [4, 5, 1, 2, 3] * list.rotate(-2); // [3, 4, 5, 1, 2] * ``` * @note Positive n rotates right, negative n rotates left. Index math is handled by resolveIndex. */ rotate(n: number): List<T>; /** * Randomly shuffles the List. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.shuffle(); // random order * ``` */ shuffle(permutations?: number): List<T>; /** * Returns a portion of the List. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.slice(1, 3); // [2, 3] * ``` */ slice(start?: number, end?: number): List<T>; /** * Tests if any item in the List satisfies the predicate. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.some(x => x > 3); // true * list.some(x => x > 5); // false * ``` */ some(fn: (item: T) => boolean): boolean; /** * Sorts the List. * * @example * ```ts * const list = List.of(3, 1, 4, 2); * list.sort(); // [1, 2, 3, 4] * list.sort((a, b) => b - a); // [4, 3, 2, 1] * ``` */ sort(compareFn?: (a: T, b: T) => number): List<T>; /** * Removes items from the List and optionally inserts new items. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.splice(1, 2); // [1, 4, 5] * list.splice(1, 2, 6, 7); // [1, 6, 7, 4, 5] * ``` * @note This method clamps the start index to valid bounds. If the start index is out of bounds, it will insert at the end. */ splice(start: number, deleteCount?: number): List<T>; splice(start: number, deleteCount: number, ...items: readonly T[]): List<T>; /** * Swaps two items in the List. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.swap(0, 2); // [3, 2, 1, 4] * ``` */ swap(index1: number, index2: number): List<T>; /** * Calculates the sum of values extracted from items using a selector function. * Returns 0 for empty lists. * * @example * ```ts * const list = List.of({ value: 1 }, { value: 2 }, { value: 3 }); * list.sumBy(x => x.value); // 6 * List.empty().sumBy(x => x.value); // 0 * ``` */ sumBy(fn: (item: T) => number): number; /** * Calculates the arithmetic mean of values extracted from items using a selector function. * Returns 0 for empty lists. * * @example * ```ts * const list = List.of({ value: 1 }, { value: 2 }, { value: 3 }); * list.averageBy(x => x.value); // 2 * List.empty().averageBy(x => x.value); // 0 * ``` */ averageBy(fn: (item: T) => number): number; /** * Calculates the median of values extracted from items using a selector function. * Returns 0 for empty lists. * For even-sized lists, returns the average of the two middle values. * * @example * ```ts * const list = List.of({ value: 1 }, { value: 2 }, { value: 3 }); * list.medianBy(x => x.value); // 2 * * const evenList = List.of({ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }); * evenList.medianBy(x => x.value); // 2.5 * ``` */ medianBy(fn: (item: T) => number): number; /** * Calculates the product of values extracted from items using a selector function. * Returns 1 for empty lists. * * @example * ```ts * const list = List.of({ value: 2 }, { value: 3 }, { value: 4 }); * list.productBy(x => x.value); // 24 * List.empty().productBy(x => x.value); // 1 * ``` */ productBy(fn: (item: T) => number): number; /** * Calculates the population variance of values extracted from items using a selector function. * Returns 0 for empty lists or lists with a single item. * * @example * ```ts * const list = List.of({ value: 2 }, { value: 4 }, { value: 4 }, { value: 4 }, { value: 5 }, { value: 5 }, { value: 7 }, { value: 9 }); * list.varianceBy(x => x.value); // 4.571428571428571 * ``` */ varianceBy(fn: (item: T) => number): number; /** * Calculates the standard deviation of values extracted from items using a selector function. * Returns 0 for empty lists or lists with a single item. * * @example * ```ts * const list = List.of({ value: 2 }, { value: 4 }, { value: 4 }, { value: 4 }, { value: 5 }, { value: 5 }, { value: 7 }, { value: 9 }); * list.standardDeviationBy(x => x.value); // 2.138089935299395 * ``` */ standardDeviationBy(fn: (item: T) => number): number; /** * Calculates the mode (most frequent value) of values extracted from items using a selector function. * Returns undefined for empty lists. * If multiple values have the same highest frequency, returns the first one encountered. * * @example * ```ts * const list = List.of({ value: 1 }, { value: 2 }, { value: 2 }, { value: 3 }); * list.modeBy(x => x.value); // 2 * ``` */ modeBy(fn: (item: T) => number): number | undefined; /** * Calculates the range (difference between max and min) of values extracted from items using a selector function. * Returns 0 for empty lists. * * @example * ```ts * const list = List.of({ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }); * list.rangeBy(x => x.value); // 3 * ``` */ rangeBy(fn: (item: T) => number): number; /** * Calculates the geometric mean of values extracted from items using a selector function. * Returns 0 for empty lists or if any value is negative. * * @example * ```ts * const list = List.of({ value: 2 }, { value: 4 }, { value: 8 }); * list.geometricMeanBy(x => x.value); // 4 * ``` */ geometricMeanBy(fn: (item: T) => number): number; /** * Calculates the harmonic mean of values extracted from items using a selector function. * Returns 0 for empty lists or if any value is 0. * * @example * ```ts * const list = List.of({ value: 1 }, { value: 2 }, { value: 4 }); * list.harmonicMeanBy(x => x.value); // 1.7142857142857142 * ``` */ harmonicMeanBy(fn: (item: T) => number): number; /** * Returns the first n items from the List. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.take(3); // [1, 2, 3] * ``` */ take(n: number): List<T>; /** * Returns items from the start of the List while the predicate is true. * * @example * ```ts * const list = List.of(1, 2, 3, 4, 5); * list.takeWhile(x => x < 3); // [1, 2] * ``` */ takeWhile(fn: (item: T) => boolean): List<T>; /** * Converts the List to an array. * * @example * ```ts * const list = List.of(1, 2, 3); * list.toArray(); // [1, 2, 3] * ``` */ toArray(): T[]; /** * Converts the List to JSON. * * @example * ```ts * const list = List.of(1, 2, 3); * list.toJSON(); // [1, 2, 3] * ``` */ toJSON(): T[]; /** * Converts the List to a Set. * * @example * ```ts * const list = List.of(1, 2, 2, 3); * list.toSet(); // Set(3) { 1, 2, 3 } * ``` */ toSet(): Set<T>; /** * Converts the List to a string. * * @example * ```ts * const list = List.of(1, 2, 3); * list.toString(); // '1,2,3' * ``` */ toString(): string; /** * Returns a List of unique items from both Lists. * * @example * ```ts * const list1 = List.of(1, 2, 3); * const list2 = List.of(3, 4, 5); * list1.union(list2); // [1, 2, 3, 4, 5] * ``` */ union(other: List<T>): List<T>; /** * Returns a List of unique items. * * @example * ```ts * const list = List.of(1, 2, 2, 3, 3, 3); * list.unique(); // [1, 2, 3] * ``` */ unique(): List<T>; /** * Returns a List of unique items based on a key function. * * @example * ```ts * const list = List.of({ id: 1 }, { id: 1 }, { id: 2 }); * list.uniqueBy(x => x.id); // [{ id: 1 }, { id: 2 }] * ``` */ uniqueBy<K>(fn: (item: T) => K): List<T>; /** * Updates an item at the specified index. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.updateAt(1, 5); // [1, 5, 3, 4] * ``` */ updateAt(index: number, item: T): List<T>; /** * Updates items that satisfy the condition. * * @example * ```ts * const list = List.of(1, 2, 3, 4); * list.updateWhere( * x => x % 2 === 0, * x => x * 2 * ); // [1, 4, 3, 8] * ``` */ updateWhere(condition: (item: T, index: number) => boolean, apply: (item: T) => T): List<T>; /** * Zips two Lists together. * * @example * ```ts * const list1 = List.of(1, 2, 3); * const list2 = List.of('a', 'b', 'c'); * list1.zip(list2); // [[1, 'a'], [2, 'b'], [3, 'c']] * ``` */ zip<U>(other: List<U>): List<[T, U]>; /** * Zips two Lists together using a function. * * @example * ```ts * const list1 = List.of(1, 2, 3); * const list2 = List.of('a', 'b', 'c'); * list1.zipWith(list2, (n, s) => n + s); // ['1a', '2b', '3c'] * ``` */ zipWith<U, V>(other: List<U>, fn: (item: T, other: U) => V): List<V>; } //#endregion export { List };