@openxmldev/linq-to-xml
Version:
LINQ to XML for TypeScript
566 lines (565 loc) • 25.6 kB
TypeScript
/**
* @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<T>} 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<T, TLinq extends LinqIterableBase<T, TLinq>> implements Iterable<T> {
protected readonly source: Iterable<T>;
protected readonly create: (source: Iterable<T>) => TLinq;
/**
* Initializes a new instance with the given sequence.
*
* @param source The source sequence.
*/
constructor(source: Iterable<T>, create: (source: Iterable<T>) => TLinq);
/**
* Returns the sequence of elements represented by this `LinqIterable<T>`.
*
* @returns The sequence of elements represented by this `LinqIterable<T>`.
*/
[Symbol.iterator](): Iterator<T>;
/**
* Filters this sequence, using zero or more filters.
*
* @param filters The filters to use.
* @returns A filtered sequence.
*/
filter(...filters: IterableFilter<T>[]): TLinq;
/**
* Filters this sequence, using the given filters.
*
* @param filters The filters to use.
* @returns A filtered sequence.
*/
applyFilters(filters: Iterable<IterableFilter<T>>): 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<TResult>(transformation: IterableValueTransform<T, TResult>): LinqIterable<TResult>;
/**
* 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<TResult>(resolution: IterableTransform<T, TResult>): 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<T>): 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<T>): TLinq;
/**
* Filters the sequence using the given predicate.
*
* @param predicate The predicate.
* @returns The filtered sequence.
*/
where(predicate: PredicateWithIndex<T>): 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<T>): 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<T>): 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<T>): 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>): 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<T>(this IEnumerable<T> 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<T>, 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>): 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<number>([]);
* 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<T>, 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>): 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<T>(this IEnumerable<T> 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<T>, 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>): 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<number>([]);
* 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<T>, 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>): 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<T>(this IEnumerable<T> 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<T>, 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>): 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<T>, 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<TKey>(keySelector: SelectorWithIndex<T, TKey>): LinqIterable<LinqIterableGrouping<TKey, T>>;
/**
* 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<TResult>(selector: SelectorWithIndex<T, TResult>): LinqIterable<TResult>;
/**
* 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<TResult>(selector: SelectorWithIndex<T, Iterable<TResult>>): LinqIterable<TResult>;
}
/**
* A LINQ iterable.
*
* @typeParam T The type of the elements of the sequence.
*/
export declare class LinqIterable<T> extends LinqIterableBase<T, LinqIterable<T>> {
constructor(source: Iterable<T>);
}
/**
* 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<TKey, T> extends LinqIterable<T> implements Grouping<TKey, T> {
readonly key: TKey;
constructor(grouping: GroupingResult<TKey, T>);
}
/**
* Converts any `Iterable<T>` into a LINQ-style iterable.
*
* @typeParam T The type of the elements of the `LinqIterable<T>`.
* @param source The source `Iterable<T>`.
* @returns A `LinqIterable<T>` instance.
*/
export declare function linqIterable<T>(source: Iterable<T>): LinqIterable<T>;