/** * @author Thomas Barnekow * @license MIT */ import { PredicateWithIndex, SelectorWithIndex } from '@tsdotnet/common-interfaces'; import { IterableFilter, IterableTransform, IterableValueTransform } from '@tsdotnet/linq/dist/IterableTransform.js'; import { Grouping, GroupingResult } from '@tsdotnet/linq/dist/transforms/groupBy.js'; /** * Abstract base class for LINQ iterables. * * @remarks * This abstract class serves as the generic base class for all LINQ iterables * provided by this library. The {@linkcode LinqIterable} class just derives * from this class and adds no further features. Other classes such as * {@linkcode LinqElements} inherit from this class and provide further methods. * The generics-based pattern used in this case means that all filter methods, * returning a `TLinq`, for example, will return instances of the subclasses. * * @typeParam T The type of the elements of the sequence. * @typeParam TLinq The type of the LINQ iterable returned by filters. */ export declare abstract class LinqIterableBase> implements Iterable { protected readonly source: Iterable; protected readonly create: (source: Iterable) => TLinq; /** * Initializes a new instance with the given sequence. * * @param source The source sequence. */ constructor(source: Iterable, create: (source: Iterable) => TLinq); /** * Returns the sequence of elements represented by this `LinqIterable`. * * @returns The sequence of elements represented by this `LinqIterable`. */ [Symbol.iterator](): Iterator; /** * Filters this sequence, using zero or more filters. * * @param filters The filters to use. * @returns A filtered sequence. */ filter(...filters: IterableFilter[]): TLinq; /** * Filters this sequence, using the given filters. * * @param filters The filters to use. * @returns A filtered sequence. */ applyFilters(filters: Iterable>): TLinq; /** * Transforms this sequence, using the given transformation. * * @transform TResult The type of the elements of the transformed sequence. * @param transformation The transformation to use. * @returns A transformed sequence. */ transform(transformation: IterableValueTransform): LinqIterable; /** * Applies the given resolution to this sequence. * * @typeParam TResult The type of the result of the resolution. * @param resolution The resolution to use. * @returns The resolved value. */ resolve(resolution: IterableTransform): TResult; /** * Returns the elements of the specified sequence or the default value if the * sequence is empty. * * @param defaultValue The default value to be returned if this sequence is empty. * @returns The elements of the specified sequence or the default value if the sequence is empty. */ defaultIfEmpty(defaultValue: T): TLinq; /** * Returns a new sequence that contains the elements from this sequence with * the first `count` elements omitted. * * @param count The number of elements to be omitted. * @returns A new sequence that contains the elements from this sequence with * the first `count` elements omitted. */ skip(count: number): TLinq; /** * Returns a new sequence that contains the elements from this sequence with * the last `count` elements omitted. * * @param count The number of elements to be omitted. * @returns A new sequence that contains the elements from this sequence with * the first `count` elements omitted. */ skipLast(count: number): TLinq; /** * Bypasses elements in a sequence as long as a specified condition is true * and then returns the remaining elements. * * @param predicate The specified condition. * @returns A new sequence with the remaining elements. */ skipWhile(predicate: PredicateWithIndex): TLinq; /** * Returns a new sequence that contains the specified number of contiguous * elements from the start of this sequence. * * @param count The number of elements to take. * @returns a new sequence that contains the specified number of contiguous * elements from the start of this sequence. */ take(count: number): TLinq; /** * Returns a new sequence that contains the specified number of contiguous * elements from the end of this sequence. * * @param count The number of elements to take. * @returns A new sequence that contains the specified number of contiguous * elements from the end of this sequence. */ takeLast(count: number): TLinq; /** * Returns a new sequence that contains elements from this sequence that occur * before the element at which the specified condition is false. * * @param predicate The specified condition. * @returns A new sequence that contains elements from this sequence that occur * before the element at which the specified condition is false. */ takeWhile(predicate: PredicateWithIndex): TLinq; /** * Filters the sequence using the given predicate. * * @param predicate The predicate. * @returns The filtered sequence. */ where(predicate: PredicateWithIndex): TLinq; /** * Returns true if the predicate is true for every element in the sequence or * if the sequence is empty. * * @param predicate The predicate. */ all(predicate: PredicateWithIndex): boolean; /** * If a predicate is provided, returns true if the predicate is true for any * element in the sequence. * If no predicate is provided, returns true if the sequence has any entries. * * @param predicate The optional predicate. */ any(predicate?: PredicateWithIndex): boolean; /** * Returns the number of elements in the sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The number of elements in the sequence. */ count(predicate?: PredicateWithIndex): number; /** * Returns the first element of this sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The first element. * @throws If the (optionally filtered) sequence is empty. * @see {@linkcode last} and {@linkcode single} */ first(predicate?: PredicateWithIndex): T; /** * Returns the first element of this sequence or `undefined`, if the sequence is empty. * * When using this API, you should appreciate the differences between C# vs. JavaScript * and TypeScript regarding the default values used for different types, e.g., as * assigned by using the `default` keyword in C# or when not explicitly initializing * fields or variables in JavaScript. * * In C#, the default values are as follows: * - nullable (e.g., `string?`) and non-nullable (e.g.,`string`) reference types: `null` * - nullable value types (e.g., `int?`, `bool?`): `null` * - non-nullable value types (e.g., `int`, `bool`): `0` and `false` * * In JavaScript, the default value for uninitialized fields or variables is `undefined` * in all cases. In TypeScript, you must either explicitly allow `undefined` in the * declaration or use the non-null assertion operator (`!`) to assign `undefined`. * * Now, let's look at the signature of the well-known `FirstOrDefault()` extension method * in C# (based on the .NET 6 documentation, which uses `TSource` instead of `T`): * * ```csharp * public static T? FirstOrDefault(this IEnumerable source); * ``` * * Based on our understanding of the default values, the most natural signature in * TypeScript is the following: * * ```typescript * firstOrDefault(): T | undefined; * ``` * * On an abstract level, the C# and TypeScript counterparts behave in the same way. * For empty sequences, they both return the respective default values. On a concrete * level, however, the language-specific difference between the default values for * non-nullable value types in C# (e.g., `int`, `bool`) and the correspnding types * in TypeScript (e.g., `number`, `boolean`) is that: * - in C#, the default values are `0` and `false`, respectively; and * - in TypeScript, the default value is `undefined` in all cases. * * Should you want to receive a value other than `undefined` in case the sequence * is empty, you can use one of the overloads that allows you to specify a default * value: * * ```typescript * firstOrDefault(defaultValue: T): T; * firstOrDefault(predicate: PredicateWithIndex, defaultValue: T): T; * ``` * * @returns The first element of this sequence or `undefined`, if this sequence is empty. * @see {@linkcode lastOrDefault} and {@linkcode singleOrDefault} */ firstOrDefault(): T | undefined; /** * Returns either (1) the first element of this sequence for which the predicate * returns `true` or (2) `undefined`, if: * - this sequence is empty or * - the predicate returns `false` for all elements of this sequence. * * @example * ```typescript * const sequence = linqIterable([1, 2, 3, 4, 5]); * const nonNullValue = sequence.firstOrDefault((n) => n > 3); // 4 * const defaultValue = sequence.firstOrDefault((n) => n > 5); // undefined * ``` * * @param predicate The predicate. * @returns Either (1) the first element of this sequence for which the predicate * returns `true` or (2) `undefined`. * @see {@linkcode lastOrDefault} and {@linkcode singleOrDefault} */ firstOrDefault(predicate: PredicateWithIndex): T | undefined; /** * Returns the first element of this sequence or the given default value, if this * sequence is empty. * * @remarks * Do not use this overload in case the elements of this sequence are functions. * See the section on [overloads](https://openxmldev.github.io/linq-to-xml/#overloads) * for details. * * @example * ```typescript * const sequence = linqIterable([]); * const defaultValue = sequence.firstOrDefault(0); // 0 * ``` * * @param defaultValue The default value to be returned if this sequence is empty. * @returns The first element of this sequence or the given default value, if this * sequence is empty. * @see {@linkcode lastOrDefault} and {@linkcode singleOrDefault} */ firstOrDefault(defaultValue: T): T; /** * Returns either (1) the first element of this sequence for which the predicate * returns `true` or (2) the given default value, if: * - this sequence is empty or * - the predicate returns `false` for all elements of this sequence. * * @example * ```typescript * const sequence = linqIterable([1, 2, 3, 4, 5]); * const nonNullValue = sequence.firstOrDefault((n) => n > 3, 0); // 4 * const defaultValue = sequence.firstOrDefault((n) => n > 5, 0); // 0 * ``` * * @param predicate The predicate. * @param defaultValue The default value. * @returns Either (1) the first element of this sequence for which the predicate * returns `true` or (2) the given default value. * @see {@linkcode lastOrDefault} and {@linkcode singleOrDefault} */ firstOrDefault(predicate: PredicateWithIndex, defaultValue: T): T; /** * Returns the last element of the sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The last element. * @throws If the (optionally filtered) sequence is empty. * @see {@linkcode first} and {@linkcode single} */ last(predicate?: PredicateWithIndex): T; /** * Returns the last element of this sequence or `undefined`, if the sequence is empty. * * When using this API, you should appreciate the differences between C# vs. JavaScript * and TypeScript regarding the default values used for different types, e.g., as * assigned by using the `default` keyword in C# or when not explicitly initializing * fields or variables in JavaScript. * * In C#, the default values are as follows: * - nullable (e.g., `string?`) and non-nullable (e.g.,`string`) reference types: `null` * - nullable value types (e.g., `int?`, `bool?`): `null` * - non-nullable value types (e.g., `int`, `bool`): `0` and `false` * * In JavaScript, the default value for uninitialized fields or variables is `undefined` * in all cases. In TypeScript, you must either explicitly allow `undefined` in the * declaration or use the non-null assertion operator (`!`) to assign `undefined`. * * Now, let's look at the signature of the well-known `LastOrDefault()` extension method * in C# (based on the .NET 6 documentation, which uses `TSource` instead of `T`): * * ```csharp * public static T? LastOrDefault(this IEnumerable source); * ``` * * Based on our understanding of the default values, the most natural signature in * TypeScript is the following: * * ```typescript * lastOrDefault(): T | undefined; * ``` * * On an abstract level, the C# and TypeScript counterparts behave in the same way. * For empty sequences, they both return the respective default values. On a concrete * level, however, the language-specific difference between the default values for * non-nullable value types in C# (e.g., `int`, `bool`) and the correspnding types * in TypeScript (e.g., `number`, `boolean`) is that: * - in C#, the default values are `0` and `false`, respectively; and * - in TypeScript, the default value is `undefined` in all cases. * * Should you want to receive a value other than `undefined` in case the sequence * is empty, you can use one of the overloads that allows you to specify a default * value: * * ```typescript * lastOrDefault(defaultValue: T): T; * lastOrDefault(predicate: PredicateWithIndex, defaultValue: T): T; * ``` * * @returns The last element of this sequence or `undefined`, if this sequence is empty. * @see {@linkcode firstOrDefault} and {@linkcode singleOrDefault} */ lastOrDefault(): T | undefined; /** * Returns either (1) the last element of this sequence for which the predicate * returns `true` or (2) `undefined`, if: * - this sequence is empty or * - the predicate returns `false` for all elements of this sequence. * * @example * ```typescript * const sequence = linqIterable([1, 2, 3, 4, 5]); * const nonNullValue = sequence.lastOrDefault((n) => n > 3); // 4 * const defaultValue = sequence.lastOrDefault((n) => n > 5); // undefined * ``` * * @param predicate The predicate. * @returns Either (1) the last element of this sequence for which the predicate * returns `true` or (2) `undefined`. * @see {@linkcode firstOrDefault} and {@linkcode singleOrDefault} */ lastOrDefault(predicate: PredicateWithIndex): T | undefined; /** * Returns the last element of this sequence or the given default value, if this * sequence is empty. * * @remarks * Do not use this overload in case the elements of this sequence are functions. * See the section on [overloads](https://openxmldev.github.io/linq-to-xml/#overloads) * for details. * * @example * ```typescript * const sequence = linqIterable([]); * const defaultValue = sequence.lastOrDefault(0); // 0 * ``` * * @param defaultValue The default value to be returned if this sequence is empty. * @returns The last element of this sequence or the given default value, if this * sequence is empty. * @see {@linkcode firstOrDefault} and {@linkcode singleOrDefault} */ lastOrDefault(defaultValue: T): T; /** * Returns either (1) the last element of this sequence for which the predicate * returns `true` or (2) the given default value, if: * - this sequence is empty or * - the predicate returns `false` for all elements of this sequence. * * @example * ```typescript * const sequence = linqIterable([1, 2, 3, 4, 5]); * const nonNullValue = sequence.lastOrDefault((n) => n > 3, 0); // 4 * const defaultValue = sequence.lastOrDefault((n) => n > 5, 0); // 0 * ``` * * @param predicate The predicate. * @param defaultValue The default value. * @returns Either (1) the last element of this sequence for which the predicate * returns `true` or (2) the given default value. * @see {@linkcode firstOrDefault} and {@linkcode singleOrDefault} */ lastOrDefault(predicate: PredicateWithIndex, defaultValue: T): T; /** * Returns the single element of the sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The single element. * @throws If the (optionally filtered) sequence does not contain exactly one element. * @see {@linkcode first} and {@linkcode last} */ single(predicate?: PredicateWithIndex): T; /** * Returns the single element of this sequence or `undefined`, if the sequence is empty. * * When using this API, you should appreciate the differences between C# vs. JavaScript * and TypeScript regarding the default values used for different types, e.g., as * assigned by using the `default` keyword in C# or when not explicitly initializing * fields or variables in JavaScript. * * In C#, the default values are as follows: * - nullable (e.g., `string?`) and non-nullable (e.g.,`string`) reference types: `null` * - nullable value types (e.g., `int?`, `bool?`): `null` * - non-nullable value types (e.g., `int`, `bool`): `0` and `false` * * In JavaScript, the default value for uninitialized fields or variables is `undefined` * in all cases. In TypeScript, you must either explicitly allow `undefined` in the * declaration or use the non-null assertion operator (`!`) to assign `undefined`. * * Now, let's look at the signature of the well-known `SingleOrDefault()` extension method * in C# (based on the .NET 6 documentation, which uses `TSource` instead of `T`): * * ```csharp * public static T? SingleOrDefault(this IEnumerable source); * ``` * * Based on our understanding of the default values, the most natural signature in * TypeScript is the following: * * ```typescript * singleOrDefault(): T | undefined; * ``` * * On an abstract level, the C# and TypeScript counterparts behave in the same way. * For empty sequences, they both return the respective default values. On a concrete * level, however, the language-specific difference between the default values for * non-nullable value types in C# (e.g., `int`, `bool`) and the correspnding types * in TypeScript (e.g., `number`, `boolean`) is that: * - in C#, the default values are `0` and `false`, respectively; and * - in TypeScript, the default value is `undefined` in all cases. * * Should you want to receive a value other than `undefined` in case the sequence * is empty, you can use one of the overloads that allows you to specify a default * value: * * ```typescript * singleOrDefault(defaultValue: T): T; * singleOrDefault(predicate: PredicateWithIndex, defaultValue: T): T; * ``` * * @returns The single element or `undefined`, if this sequence is empty. * @throws If this sequence contains more than one element. * @see {@linkcode firstOrDefault} and {@linkcode lastOrDefault} */ singleOrDefault(): T | undefined; /** * Returns either (1) the single element of this sequence for which the predicate * returns `true` or (2) `undefined`, if: * - this sequence is empty or * - the predicate returns `false` for all elements of this sequence. * * @param predicate The predicate. * @returns Either (1) the single element of this sequence for which the predicate * returns `true` or (2) `undefined`, if the predicate returns `false` for all * elements. * @throws If there is more than one element for which the predicate returns `true`. * @see {@linkcode firstOrDefault} and {@linkcode lastOrDefault} */ singleOrDefault(predicate: PredicateWithIndex): T | undefined; /** * Returns the single element of this sequence or the given default value, if this * sequence is empty. * * @remarks * Do not use this overload in case the elements of this sequence are functions. * See the section on [overloads](https://openxmldev.github.io/linq-to-xml/#overloads) * for details. * * @param defaultValue The default value to be returned if this sequence is empty. * @returns The single element of this sequence or the given default value, if this * sequence is empty. * @throws If this sequence contains more than one element. * @see {@linkcode firstOrDefault} and {@linkcode lastOrDefault} */ singleOrDefault(defaultValue: T): T; /** * Returns either (1) the single element of this sequence for which the predicate * returns `true` or (2) the given default value, if: * - this sequence is empty or * - the predicate returns `false` for all elements of this sequence. * * @param predicate The predicate. * @param defaultValue The default value to be returned if this sequence is empty or * the predicate returns false for all elements. * @returns Either (1) the single element of this sequence for which the predicate * returns `true` or (2) the given default value, if the predicate returns * `false` for all elements. * @throws If there is more than one element for which the predicate returns `true`. * @see {@linkcode firstOrDefault} and {@linkcode lastOrDefault} */ singleOrDefault(predicate: PredicateWithIndex, defaultValue: T): T; /** * Returns all the elements in the sequence as an array. */ toArray(): T[]; /** * Groups elements by selected key. * * @typeParam TKey The type of the grouping keys. * @param keySelector Selects the grouping keys. * @returns The grouped elements. */ groupBy(keySelector: SelectorWithIndex): LinqIterable>; /** * Projects, or maps, each element of a sequence into a new form. * * @typeParam TResult The type of the elements of the projected, or mapped, sequence. * @param selector The selector used to project, or map, the elements. * @returns The projected, or mapped, sequence. */ select(selector: SelectorWithIndex): LinqIterable; /** * Merges the selected sequences into one flat sequence. * * @typeParam TResult The type of the elements of the flat sequence. * @param selector The selector. * @returns The merged, flat sequence. */ selectMany(selector: SelectorWithIndex>): LinqIterable; } /** * A LINQ iterable. * * @typeParam T The type of the elements of the sequence. */ export declare class LinqIterable extends LinqIterableBase> { constructor(source: Iterable); } /** * Represents a grouping of sequence elements. * * @typeParam TKey The type of the grouping keys. * @typeParam T The type of the grouped elements. */ export declare class LinqIterableGrouping extends LinqIterable implements Grouping { readonly key: TKey; constructor(grouping: GroupingResult); } /** * Converts any `Iterable` into a LINQ-style iterable. * * @typeParam T The type of the elements of the `LinqIterable`. * @param source The source `Iterable`. * @returns A `LinqIterable` instance. */ export declare function linqIterable(source: Iterable): LinqIterable;