swisslist
Version:
A functional, immutable list implementation with a rich set of methods for manipulating collections.
885 lines • 22.7 kB
TypeScript
//#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 };