type OperationFunction<TInput, TOutput> = (iterable: Iterable<TInput>) => Iterable<TOutput>;
type AsyncOperationFunction<TInput, TOutput> = (iterable: AsyncIterable<TInput>) => AsyncIterable<TOutput>;

type CollectorFunction<TInput, TOutput> = (iterable: Iterable<TInput>) => TOutput;
type AsyncCollectorFunction<TInput, TOutput> = (iterable: AsyncIterable<TInput>) => PromiseLike<TOutput>;

/** Wrapper class to extend the functionality of an Iterable */
declare class AsyncStream<T> implements AsyncIterable<T> {
    private readonly asyncIterable;
    [Symbol.asyncIterator](): AsyncIterator<T>;
    constructor(asyncIterable?: AsyncIterable<T> | null);
    /** Calls a collector function on the Iterable */
    collectAsync<O>(collector: AsyncCollectorFunction<T, O>): PromiseLike<O>;
    /** Calls an operation function on the Iterable then returns the result as a Stream
     *  allowing to chain it with more Stream related methods. */
    pipeAsync(): AsyncStream<T>;
    pipeAsync<A>(op1: AsyncOperationFunction<T, A>): AsyncStream<A>;
    pipeAsync<A, B>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>): AsyncStream<B>;
    pipeAsync<A, B, C>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>): AsyncStream<C>;
    pipeAsync<A, B, C, D>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>): AsyncStream<D>;
    pipeAsync<A, B, C, D, E>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>): AsyncStream<E>;
    pipeAsync<A, B, C, D, E, F>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>): AsyncStream<F>;
    pipeAsync<A, B, C, D, E, F, G>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>): AsyncStream<G>;
    pipeAsync<A, B, C, D, E, F, G, H>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>, op8: AsyncOperationFunction<G, H>): AsyncStream<H>;
    pipeAsync<A, B, C, D, E, F, G, H, I>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>, op8: AsyncOperationFunction<G, H>, op9: AsyncOperationFunction<H, I>): AsyncStream<H>;
    pipeAsync<A, B, C, D, E, F, G, H, I>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>, op8: AsyncOperationFunction<G, H>, op9: AsyncOperationFunction<H, I>): AsyncStream<I>;
    pipeAsync(...ops: AsyncOperationFunction<T, T>[]): AsyncStream<T>;
}

/** Wrapper class to extend the functionality of an Iterable */
declare class Stream<T> extends AsyncStream<T> implements Iterable<T> {
    private readonly iterable;
    constructor(iterable?: Iterable<T> | null);
    [Symbol.iterator](): Iterator<T>;
    [Symbol.asyncIterator](): AsyncIterator<T>;
    /** Calls a collector function on the Iterable */
    collect<O>(collector: CollectorFunction<T, O>): O;
    /** Calls an operation function on the Iterable then returns the result as a Stream
     *  allowing to chain it with more Stream related methods. */
    pipe(): Stream<T>;
    pipe<A>(op1: OperationFunction<T, A>): Stream<A>;
    pipe<A, B>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>): Stream<B>;
    pipe<A, B, C>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>): Stream<C>;
    pipe<A, B, C, D>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>): Stream<D>;
    pipe<A, B, C, D, E>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>): Stream<E>;
    pipe<A, B, C, D, E, F>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>): Stream<F>;
    pipe<A, B, C, D, E, F, G>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>): Stream<G>;
    pipe<A, B, C, D, E, F, G, H>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>, op8: OperationFunction<G, H>): Stream<H>;
    pipe<A, B, C, D, E, F, G, H, I>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>, op8: OperationFunction<G, H>, op9: OperationFunction<H, I>): Stream<H>;
    pipe<A, B, C, D, E, F, G, H, I>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>, op8: OperationFunction<G, H>, op9: OperationFunction<H, I>): Stream<I>;
    pipe(...ops: OperationFunction<T, T>[]): Stream<T>;
}

/**
  * Returns a Stream that yields elements of all Iterable parameters in order.
  * @param iterables Iterables to concatenate.
  * @typeParam T Type of items in the Iterables.
  * @returns Stream that yields elements of all Iterables in order.
  */
declare function concat<T>(...iterables: Array<Iterable<T>>): Stream<T>;
declare const chain: typeof concat;

/**
 * Returns a Stream that yields elements of all Iterable parameters in order.
 */
declare function concatAsync<T>(...iterables: Array<Iterable<T> | AsyncIterable<T>>): AsyncStream<T>;
declare const chainAsync: typeof concatAsync;

/**
 * Returns a Stream that infinitely yields elements of the Iterable parameter.
 */
declare function cycle<T>(iterable: Iterable<T>): Stream<T>;

/**
 * Returns a Stream that is empty.
 * @typeParam T Type of items in the Stream.
 * @returns Stream that is empty.
 *
 * @example
 * ```typescript
 * const result = empty();
 * console.log([...result]); // []
 * ```
 */
declare function empty<T>(): Stream<T>;

/**
 * Returns a Stream that yields the elements of the Iterable parameter.
 * @typeParam T Type of items in the Stream.
 * @param iterable Iterable to create the Stream from.
 * @returns Stream that yields the elements of the Iterable.
 *
 * @example
 * ```typescript
 * const result = from('ABCD');
 * console.log([...result]); // ['A', 'B', 'C', 'D']
 * ```
 */
declare function from<T>(iterable?: Iterable<T>): Stream<T>;
declare const stream: typeof from;

/**
 * Creates a Stream from an iterable (Array, Set, Map, Stream...)
 */
declare function fromAsync<T>(iterable?: AsyncIterable<T>): AsyncStream<T>;
declare const streamAsync: typeof fromAsync;

/**
  * Returns a Stream that yields the specified entries.
  * @typeParam T Type of items in the Stream.
  * @param entries Entries to create the Stream from.
  * @returns Stream that yields the specified entries.
  *
  * @example
  * ```typescript
  * const result = of(1, 2, 3);
  * console.log([...result]); // [1, 2, 3]
  * ```
  */
declare function of<T>(...entries: T[]): Stream<T>;
declare const streamOf: typeof of;

/**
 * Returns a Stream that merges elements from both iterables by taking one
 * element from each, passing them to the function, and yielding the result.
 *
 * @param a The first iterable to merge.
 * @param b The second iterable to merge.
 * @param productFunction The function that merges the elements.
 * @returns A Stream that merges elements from both iterables.
 *
 * @example
 * ```typescript
 * const result = product('ABCD', 'xy', (a, b) => `${a}${b}`);
 * console.log([...result]); // ['Ax', 'Ay', 'Bx', 'By', 'Cx', 'Cy', 'Dx', 'Dy']
 * ```
 */
declare function product<A, B, O>(a: Iterable<A>, b: Iterable<B>, productFunction: (a: A, b: B) => O): Stream<O>;

/**
  * Returns a Stream that yields numbers starting from 'start' up to 'start + count - 1'.
  * @param start The first number in the range.
  * @param count The number of elements in the range.
  * @param by The step between elements.
  * @returns A Stream that yields numbers in the range.
  *
  * @example
  * ```typescript
  * const result = range(1, 5, 2);
  * console.log([...result]); // [1, 3, 5]
  * ```
  */
declare function range(start: number, count: number, by?: number): Stream<number>;

declare function isNotNull<T>(value: T | null | undefined): value is NonNullable<T>;
declare function isFunction(x: unknown): x is Function;
declare function isIterable<T>(x: Iterable<T> | AsyncIterable<T>): x is Iterable<T>;
declare function isNotNullOrEmpty<T extends {
    length: number;
}>(value: T | null | undefined): value is NonNullable<T>;
declare function isNotNullOrWhitespace(value: string | null | undefined): value is NonNullable<string>;

type EqualsFunction<T> = (a: T, b: T) => boolean;
type CompareFunction<T> = (a: T, b: T) => number;
type MaybeAsyncValue<T> = T | PromiseLike<T>;
type ReduceFunction<T, O = T> = (previous: O, current: T, index: number) => O;
type AsyncReduceFunction<T, O = T> = (previous: O, current: T, index: number) => MaybeAsyncValue<O>;
type ValueOrFactory<T> = T | (() => T);
type PredicateFunction<T> = (item: T, index: number) => boolean;
type MaybeAsyncPredicateFunction<T> = (item: T, index: number) => boolean | Promise<boolean>;
type TypeGuardFunction<T, TOfType extends T> = (item: T, index: number) => item is TOfType;
type CallbackFunction<T> = (item: T, index: number) => void;
type MaybeAsyncCallbackFunction<T> = (item: T, index: number) => void | Promise<void>;
type MapperFunction<T, O> = (item: T, index: number) => O;
type AsyncMapperFunction<T, O> = (item: T, index: number) => PromiseLike<O>;

/**
 * Returns a Stream that yields the same value 'times' number of times.
 * @param value Value to repeat.
 * @param times Number of times to repeat the value.
 * @typeParam T Type of the value.
 * @returns A Stream that yields the value 'times' number of times.
 *
 * @example
 * ```typescript
 * const result = repeat('A', 3);
 * console.log([...result]); // ['A', 'A', 'A']
 * ```
 */
declare function repeat<T>(value: ValueOrFactory<T>, times?: number): Stream<T>;

/**
 * Returns a Stream that merges elements from both iterables by taking one
 * element from each, passing them to the function, and yielding the result.
 *
 * @param a The first iterable to merge.
 * @param b The second iterable to merge.
 * @param zipFunction The function that merges the elements.
 * @returns A Stream that merges elements from both iterables.
 *
 * @example
 * ```typescript
 * const result = zip('ABCD', 'xy', (a, b) => `${a}${b}`);
 * console.log([...result]); // ['Ax', 'By']
 * ```
 */
declare function zip<A, B, O>(a: Iterable<A>, b: Iterable<B>, zipFunction: (a: A, b: B) => O): Stream<O>;

/**
 * Returns a Stream that merges elements from both iterables by taking one
 * element from each, passing them to the function, and yielding the result.
 */
declare function zipAsync<A, B, O>(a: AsyncIterable<A>, b: AsyncIterable<B>, zipFunction: (a: A, b: B) => O): AsyncStream<O>;

/**
 * Returns a Stream that merges elements from both iterables by taking one
 * element from each, passing them to the function, and yielding the result.
 *
 * @param a The first iterable to merge.
 * @param b The second iterable to merge.
 * @param fillValue The value or factory to use when one iterable is done.
 * @param zipFunction The function that merges the elements.
 * @returns A Stream that merges elements from both iterables.
 *
 * @example
 * ```typescript
 * const result = zipLongest('ABCD', 'xy', ' ', (a, b) => `${a}${b}`);
 * console.log([...result]); // ['Ax', 'By', 'C ', 'D ']
 * ```
 */
declare function zipLongest<A, B, F, O>(a: Iterable<A>, b: Iterable<B>, fillValue: ValueOrFactory<F>, zipFunction: (a: A | F, b: B | F) => O): Stream<O>;

/**
 * Appends the given Iterables to the end of the source Iterable.
 * @param iterables Iterables to append.
 * @typeParam T Type of items in the Iterables.
 * @returns Returns a new Iterable that yields the elements of the source Iterable followed by the elements of the given Iterables.
 *
 * @example
 * ```typescript
 * const result = appendWith([4, 5, 6], [7, 8, 9])([1, 2, 3]);
 * console.log([...result]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
 * ```
 */
declare function appendWith<T>(...iterables: Iterable<T>[]): OperationFunction<T, T>;

/** Concatenates the Iterable with other Iterables in order */
declare function appendWithAsync<T>(...iterables: Iterable<T>[]): AsyncOperationFunction<T, T>;

/** Returns an Iterable that yields only array entries of the source Iterable that satisfy the function. */
declare function arrayFilter<T>(predicate: (entry: T, index: number) => boolean): OperationFunction<T[], T[]>;

/** Returns an Iterable that yields array entries of the source Iterable transformed using the function */
declare function arrayMap<T, O>(mapper: (entry: T, index: number) => O): OperationFunction<T[], O[]>;

/**
 * Buffers the source elements into arrays of 'size' elements.
 * @param size The number of elements in each buffer.
 * @typeParam T Type of the elements.
 * @returns Operation that buffers the source elements.
 *
 * @example
 * ```typescript
 * const result = buffer(3)([1, 2, 3, 4, 5, 6]);
 * console.log([...result]); // [[1, 2, 3], [4, 5, 6]]
 * ```
 */
declare function buffer<T>(size: number): OperationFunction<T, T[]>;

/** Returns an Iterable that yields array of entries of the source Iterable with the given length. */
declare function bufferAsync<T>(size: number): AsyncOperationFunction<T, T[]>;

/** Type-safe helper operation that concatenates multiple operations in order. */
declare function compound<T>(): OperationFunction<T, T>;
declare function compound<T, A>(op1: OperationFunction<T, A>): OperationFunction<T, A>;
declare function compound<T, A, B>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>): OperationFunction<T, B>;
declare function compound<T, A, B, C>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>): OperationFunction<T, C>;
declare function compound<T, A, B, C, D>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>): OperationFunction<T, D>;
declare function compound<T, A, B, C, D, E>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>): OperationFunction<T, E>;
declare function compound<T, A, B, C, D, E, F>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>): OperationFunction<T, F>;
declare function compound<T, A, B, C, D, E, F, G>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>): OperationFunction<T, G>;
declare function compound<T, A, B, C, D, E, F, G, H>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>, op8: OperationFunction<G, H>): OperationFunction<T, H>;
declare function compound<T, A, B, C, D, E, F, G, H, I>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>, op8: OperationFunction<G, H>, op9: OperationFunction<H, I>): OperationFunction<T, I>;
declare function compound<T, A, B, C, D, E, F, G, H, I, J>(op1: OperationFunction<T, A>, op2: OperationFunction<A, B>, op3: OperationFunction<B, C>, op4: OperationFunction<C, D>, op5: OperationFunction<D, E>, op6: OperationFunction<E, F>, op7: OperationFunction<F, G>, op8: OperationFunction<G, H>, op9: OperationFunction<H, I>, op10: OperationFunction<I, J>): OperationFunction<T, J>;
declare const pipe: typeof compound;

/** Type-safe helper operation that concatenates multiple operations in order. */
declare function compoundAsync<T>(): AsyncOperationFunction<T, T>;
declare function compoundAsync<T, A>(op1: AsyncOperationFunction<T, A>): AsyncOperationFunction<T, A>;
declare function compoundAsync<T, A, B>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>): AsyncOperationFunction<T, B>;
declare function compoundAsync<T, A, B, C>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>): AsyncOperationFunction<T, C>;
declare function compoundAsync<T, A, B, C, D>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>): AsyncOperationFunction<T, D>;
declare function compoundAsync<T, A, B, C, D, E>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>): AsyncOperationFunction<T, E>;
declare function compoundAsync<T, A, B, C, D, E, F>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>): AsyncOperationFunction<T, F>;
declare function compoundAsync<T, A, B, C, D, E, F, G>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>): AsyncOperationFunction<T, G>;
declare function compoundAsync<T, A, B, C, D, E, F, G, H>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>, op8: AsyncOperationFunction<G, H>): AsyncOperationFunction<T, H>;
declare function compoundAsync<T, A, B, C, D, E, F, G, H, I>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>, op8: AsyncOperationFunction<G, H>, op9: AsyncOperationFunction<H, I>): AsyncOperationFunction<T, I>;
declare function compoundAsync<T, A, B, C, D, E, F, G, H, I, J>(op1: AsyncOperationFunction<T, A>, op2: AsyncOperationFunction<A, B>, op3: AsyncOperationFunction<B, C>, op4: AsyncOperationFunction<C, D>, op5: AsyncOperationFunction<D, E>, op6: AsyncOperationFunction<E, F>, op7: AsyncOperationFunction<F, G>, op8: AsyncOperationFunction<G, H>, op9: AsyncOperationFunction<H, I>, op10: AsyncOperationFunction<I, J>): AsyncOperationFunction<T, unknown>;
declare const pipeAsync: typeof compoundAsync;

/**
 * Concatenates the given Iterables to the end of the source Iterable.
 * @param iterables Iterables to concatenate.
 * @typeParam T Type of items in the Iterables.
 * @returns Returns a new Iterable that yields the elements of the source Iterable followed by the elements of the given Iterables.
 *
 * @example
 * ```typescript
 * const result = concatWith([4, 5, 6], [7, 8, 9])([1, 2, 3]);
 * console.log([...result]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
 * ```
 */
declare function concatWith<T>(...iterables: Iterable<T>[]): OperationFunction<T, T>;

/** Concatenates the Iterable with other Iterables in order */
declare function concatWithAsync<T>(...iterables: Array<AsyncIterable<T> | Iterable<T>>): AsyncOperationFunction<T, T>;

/**
 * Emits a default value if the source is empty.
 * @param defaultValue Value to emit if the source is empty.
 * @typeParam T Type of items emitted by the source.
 * @returns Operation that emits a default value if the source is empty.
 *
 * @example
 * ```typescript
 * const result = defaultIfEmpty('A')([]);
 * console.log([...result]); // ['A']
 * ```
 */
declare function defaultIfEmpty<T>(defaultValue: ValueOrFactory<T>): OperationFunction<T, T>;

/** Returns an Iterable with the value parameter if the source Iterable is empty. */
declare function defaultIfEmptyAsync<T>(defaultValue: ValueOrFactory<T>): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields distinct elements from the source.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields distinct elements from the source.
 *
 * @example
 * ```typescript
 * const result = distinct()([1, 2, 1, 3, 2, 4]);
 * console.log([...result]); // [1, 2, 3, 4]
 * ```
 */
declare function distinct<T>(): OperationFunction<T, T>;

/** Returns an Iterable that yields only entries of the source Iterable without duplicates. */
declare function distinctAsync<T>(): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields distinct elements from the source based on the equals function.
 * @param equalsFunction Function to compare elements.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields distinct elements from the source.
 *
 * @example
 * ```typescript
 * const result = distinctBy<number>((a, b) => a % 2 === b % 2)([1, 2, 1, 3, 2, 4]);
 * console.log([...result]); // [1, 2]
 * ```
 */
declare function distinctBy<T>(equalsFunction?: EqualsFunction<T>): OperationFunction<T, T>;

/** Returns an Iterable that yields only entries of the source Iterable without duplicates. */
declare function distinctByAsync<T>(equalsFunction?: EqualsFunction<T>): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields elements from the source that are distinct from the previous element.
 * @param equalsFunction Function to compare elements.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields elements from the source that are distinct from the previous element.
 *
 * @example
 * ```typescript
 * const result = distinctUntilChanged<number>()([1, 1, 2, 2, 3, 3]);
 * console.log([...result]); // [1, 2, 3]
 * ```
 */
declare function distinctUntilChanged<T>(equalsFunction?: EqualsFunction<T>): OperationFunction<T, T>;

/** Returns an Iterable that yields only entries of the source Iterable without duplicates. */
declare function distinctUntilChangedAsync<T>(equalsFunction?: EqualsFunction<T>): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields elements from the source that are distinct from the previous element based on the key.
 * @param key Key to compare elements.
 * @param equalsFunction Function to compare elements.
 * @typeParam T Type of items in the source.
 *
 * @example
 * ```typescript
 * const result = distinctUntilKeyChanged('a')([{ a: 1 }, { a: 1 }, { a: 2 }, { a: 2 }, { a: 3 }, { a: 3 }]);
 * console.log([...result]); // [{ a: 1 }, { a: 2 }, { a: 3 }]
 * ```
 */
declare function distinctUntilKeyChanged<T, K extends keyof T>(key: K, equalsFunction?: EqualsFunction<T[K]>): OperationFunction<T, T>;

declare function distinctUntilKeyChangedAsync<T, K extends keyof T>(key: K, equalsFunction?: EqualsFunction<T[K]>): AsyncOperationFunction<T, T>;

/**
 * Concatenates the given values to the end of the source Iterable.
 * @param values Values to concatenate.
 * @typeParam T Type of items in the Iterables.
 * @returns Returns a new Iterable that yields the elements of the source Iterable followed by the given values.
 *
 * @example
 * ```typescript
 * const result = endWith(4, 5, 6)([1, 2, 3]);
 * console.log([...result]); // [1, 2, 3, 4, 5, 6]
 * ```
 */
declare function endWith<T>(...values: T[]): OperationFunction<T, T>;

/** Returns an Iterable with the entries of the source Iterable then the parameter value. */
declare function endWithAsync<T>(...values: T[]): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields elements that are falsy.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields elements that are falsy.
 *
 * @example
 * ```typescript
 * const result = falsy<number>()([0, 1, 2, 3, 4]);
 * console.log([...result]); // [0]
 * ```
 */
declare function falsy<T>(): OperationFunction<T, T>;

/** Returns an Iterable that yields only entries of the source Iterable with falsy value. */
declare function falsyAsync<T>(): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields elements from the source that satisfy the predicate.
 * @param predicate Predicate to filter elements.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields elements from the source that satisfy the predicate.
 *
 * @example
 * ```typescript
 * const result = filter((x) => x % 2 === 0)([1, 2, 3, 4, 5]);
 * console.log([...result]); // [2, 4]
 * ```
 */
declare function filter<T, TOfType extends T = T>(predicate: PredicateFunction<T> | TypeGuardFunction<T, TOfType>): OperationFunction<T, T>;

/** Returns an Iterable that yields only entries of the source Iterable that satisfy the function. */
declare function filterAsync<T>(predicate: PredicateFunction<T>): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields elements from the source that are Iterable and flattens them.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields elements from the source that are Iterable and flattens them.
 *
 * @example
 * ```typescript
 * const result = flat<number>()([[1, 2], [3, 4]]);
 * console.log([...result]); // [1, 2, 3, 4]
 * ```
 */
declare function flat<T>(): OperationFunction<Iterable<T>, T>;
declare const flatten: typeof flat;

/** Returns an Iterable that yields the inner entries of array entries of the source Iterable. */
declare function flatAsync<T>(): AsyncOperationFunction<Iterable<T>, T>;
declare const flattenAsync: typeof flatAsync;

/**
 * Maps each element to an Iterable and flattens the result.
 * @param mapper Mapping function.
 * @typeParam T Type of items in the source.
 * @typeParam O Type of items in the resulting Iterable.
 * @returns Operation that maps each element to an Iterable and flattens the result.
 *
 * @example
 * ```typescript
 * const result = flatMap<number, number>((value) => [value, value + 1])([1, 2, 3]);
 * console.log([...result]); // [1, 2, 2, 3, 3, 4]
 * ```
 */
declare function flatMap<T, O>(mapper: (value: T, index: number) => Iterable<O>): OperationFunction<T, O>;

/**
 * Returns an Iterable that yields the inner entries of the
 * result produced by the function.
 */
declare function flatMapAsync<T, O>(mapper: (value: T, index: number) => Iterable<O>): AsyncOperationFunction<T, O>;

/**
 * Returns a Stream that yields elements from the source transformed by the mapper.
 * @param mapper Function to transform elements.
 * @typeParam T Type of items in the source.
 * @typeParam O Type of items in the result.
 * @returns Operation that yields elements from the source transformed by the mapper.
 *
 * @example
 * ```typescript
 * const result = map((x) => x * 2)([1, 2, 3]);
 * console.log([...result]); // [2, 4, 6]
 * ```
 */
declare function map<T, O>(mapper: (value: T, index: number) => O): OperationFunction<T, O>;

/** Returns an Iterable that yields entries of the source Iterable transformed using the function */
declare function mapAsync<T, O>(mapper: MapperFunction<T, O> | AsyncMapperFunction<T, O>): AsyncOperationFunction<T, O>;

/**
 * Returns a Stream that yields the same elements as the source.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields the same elements as the source.
 *
 * @example
 * ```typescript
 * const result = noop<number>()([1, 2, 3]);
 * console.log([...result]); // [1, 2, 3]
 * ```
 */
declare function noop<T>(): OperationFunction<T, T>;

/** Simply returns every entry from the source Iterable */
declare function noopAsync<T>(): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields elements that are not `null`, `undefined`, or empty.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields elements that are not `null`, `undefined`, or empty.
 *
 * @example
 * ```typescript
 * const result = notNullOrEmpty<string>()(["", "a", null, "b", undefined, "c"]);
 * console.log([...result]); // ["a", "b", "c"]
 * ```
 */
declare function notNullOrEmpty<T extends {
    length: number;
}>(): OperationFunction<T | null | undefined, NonNullable<T>>;

/** Returns an Iterable that yields only the non-null / non-undefined / non-empty entries of the source Iterable. */
declare function notNullOrEmptyAsync<T extends {
    length: number;
}>(): AsyncOperationFunction<T | undefined | null, NonNullable<T>>;

/**
 * Returns a Stream that yields elements that are not `null`, `undefined`, or whitespace.
 * @returns Operation that yields elements that are not `null`, `undefined`, or whitespace.
 *
 * @example
 * ```typescript
 * const result = notNullOrWhitespace<string>()(["", "a", null, "b", undefined, "c", " "]);
 * console.log([...result]); // ["a", "b", "c"]
 * ```
 */
declare function notNullOrWhitespace(): OperationFunction<string | null | undefined, NonNullable<string>>;

/** Returns an Iterable that yields only the non-null / non-undefined / non-empty entries of the source Iterable. */
declare function notNullOrWhitespaceAsync(): AsyncOperationFunction<string | null | undefined, NonNullable<string>>;

/**
 * Returns a Stream that yields elements that are of the specified type.
 * @typeParam T Type of items in the source.
 * @typeParam TOfType Type of items to yield.
 * @param predicate A function that determines if an item is of the specified type.
 * @returns Operation that yields elements that are of the specified type.
 *
 * @example
 * ```typescript
 * const result = ofType<string, string>()(Number)(["a", 1, "b", 2]);
 * console.log([...result]); // [1, 2]
 * ```
 */
declare function ofType<T, TOfType extends T = T>(predicate: TypeGuardFunction<T, TOfType>): OperationFunction<T, TOfType>;

/** Returns and casts an Iterable that yields only entries of the source Iterable that satisfy the given type-guard function. */
declare function ofTypeAsync<T, TOfType extends T = T>(predicate: TypeGuardFunction<T, TOfType>): AsyncOperationFunction<T, TOfType>;

/**
 * Returns a Stream that yields pairs of consecutive elements from the source.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields pairs of consecutive elements from the source.
 *
 * @example
 * ```typescript
 * const result = pairwise<number>()([1, 2, 3, 4]);
 * console.log([...result]); // [[1, 2], [2, 3], [3, 4]]
 * ```
 */
declare function pairwise<T>(): OperationFunction<T, [T, T]>;

/** Returns an Iterable that yields the current and the previous entry of the source Iterable. */
declare function pairwiseAsync<T>(): AsyncOperationFunction<T, [T, T]>;

/**
 * Skips the first `count` elements from the source.
 * @param count Number of elements to skip.
 * @typeParam T Type of items in the source.
 * @returns Operation that skips the first `count` elements from the source.
 *
 * @example
 * ```typescript
 * const result = skip<number>(2)([1, 2, 3, 4]);
 * console.log([...result]); // [3, 4]
 * ```
 */
declare function skip<T>(count: number): OperationFunction<T, T>;

/** Returns an Iterable skipping the given amount of entries of the source Iterable. */
declare function skipAsync<T>(count: number): AsyncOperationFunction<T, T>;

/**
 * Skips elements from the source while the predicate returns `true`.
 * @param predicate Predicate function to determine if an element should be skipped.
 * @typeParam T Type of items in the source.
 * @returns Operation that skips elements from the source while the predicate returns `true`.
 *
 * @example
 * ```typescript
 * const result = skipWhile<number>((x) => x < 3)([1, 2, 3, 4]);
 * console.log([...result]); // [3, 4]
 * ```
 */
declare function skipWhile<T>(predicate: PredicateFunction<T>): OperationFunction<T, T>;

/** Returns an Iterable skipping entries of the source Iterable while the parameter function returns true. */
declare function skipWhileAsync<T>(predicate: PredicateFunction<T>): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields elements from the source followed by the provided values.
 * @typeParam T Type of items in the source.
 * @param values Values to yield after the source.
 * @returns Operation that yields elements from the source followed by the provided values.
 *
 * @example
 * ```typescript
 * const result = startWith(0, 1, 2)([3, 4, 5]);
 * console.log([...result]); // [0, 1, 2, 3, 4, 5]
 * ```
 */
declare function startWith<T>(...values: T[]): OperationFunction<T, T>;

/** Returns an Iterable started with the value parameter then the entries of the source Iterable. */
declare function startWithAsync<T>(...values: T[]): AsyncOperationFunction<T, T>;

/**
 * Takes the first `count` elements from the source.
 * @param count Number of elements to take.
 * @typeParam T Type of items in the source.
 * @returns Operation that takes the first `count` elements from the source.
 *
 * @example
 * ```typescript
 * const result = take<number>(2)([1, 2, 3, 4]);
 * console.log([...result]); // [1, 2]
 * ```
 */
declare function take<T>(count: number): OperationFunction<T, T>;

/** Returns an Iterable taking the given amount of entries of the source Iterable. */
declare function takeAsync<T>(count: number): AsyncOperationFunction<T, T>;

/**
 * Takes elements from the source while the predicate returns `true`.
 * @param predicate Predicate function to determine if an element should be taken.
 * @typeParam T Type of items in the source.
 * @returns Operation that takes elements from the source while the predicate returns `true`.
 *
 * @example
 * ```typescript
 * const result = takeWhile<number>((x) => x < 3)([1, 2, 3, 4]);
 * console.log([...result]); // [1, 2]
 * ```
 */
declare function takeWhile<T>(predicate: PredicateFunction<T>): OperationFunction<T, T>;

/** Returns an Iterable taking entries of the source Iterable while the parameter function returns true. */
declare function takeWhileAsync<T>(predicate: PredicateFunction<T>): AsyncOperationFunction<T, T>;

/**
 * Invokes a callback for each element in the source.
 * @param callback Callback function to invoke for each element.
 * @typeParam T Type of items in the source.
 * @returns Operation that invokes a callback for each element in the source.
 *
 * @example
 * ```typescript
 * const result = tap<number>((x) => console.log(x))([1, 2, 3]);
 * // Logs:
 * // 1
 * // 2
 * // 3
 * console.log([...result]); // [1, 2, 3]
 * ```
 */
declare function tap<T>(callback: CallbackFunction<T>): OperationFunction<T, T>;

/** Calls a callback function on each entry */
declare function tapAsync<T>(callback: CallbackFunction<T>): AsyncOperationFunction<T, T>;

/**
 * Returns a Stream that yields truthy elements from the source.
 * @typeParam T Type of items in the source.
 * @returns Operation that yields truthy elements from the source.
 *
 * @example
 * ```typescript
 * const result = truthy<number>()([0, 1, 2, 3]);
 * console.log([...result]); // [1, 2, 3]
 * ```
 */
declare function truthy<T>(): OperationFunction<T, T>;

/** Returns an Iterable that yields only entries of the source Iterable with truthy value. */
declare function truthyAsync<T>(): AsyncOperationFunction<T, T>;

/**
 * Checks if all elements in the source satisfy the predicate.
 * @param predicate Predicate function to determine if an element satisfies a condition.
 * @typeParam T Type of items in the source.
 * @returns Collector that checks if all elements in the source satisfy the predicate.
 *
 * @example
 * ```typescript
 * const result = all<number>((x) => x > 0)([1, 2, 3]);
 * console.log(result); // true
 * ```
 */
declare function all<T>(predicate: PredicateFunction<T>): CollectorFunction<T, boolean>;
declare const every: typeof all;

/** Returns true if all entries satisfy the 'predicate' function. */
declare function allAsync<T>(predicate: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, boolean>;
declare const everyAsync: typeof allAsync;

/**
 * Checks if any element in the source satisfies the predicate.
 * @param predicate Predicate function to determine if an element satisfies a condition.
 * @typeParam T Type of items in the source.
 * @returns Collector that checks if any element in the source satisfies the predicate.
 *
 * @example
 * ```typescript
 * const result = any<number>((x) => x > 2)([1, 2, 3]);
 * console.log(result); // true
 * ```
 */
declare function any<T>(predicate?: PredicateFunction<T>): CollectorFunction<T, boolean>;
declare const some: typeof any;

/** Returns true if at least one of the entries satisfies the 'predicate' function. */
declare function anyAsync<T>(predicate?: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, boolean>;
declare const someAsync: typeof anyAsync;

/**
 * Checks if the source contains a specific value.
 * @param value Value to check for.
 * @param equalsFunction Optional function to compare values.
 * @typeParam T Type of items in the source.
 * @returns Collector that checks if the source contains a specific value.
 *
 * @example
 * ```typescript
 * const result = contains(2)([1, 2, 3]);
 * console.log(result); // true
 * ```
 */
declare function contains<T>(value: T, equalsFunction?: EqualsFunction<T>): CollectorFunction<T, boolean>;
declare const includes: typeof contains;

/** Returns if at least one of the entries equals with the given 'value'. */
declare function containsAsync<T>(value: T, equalsFunction?: EqualsFunction<T>): AsyncCollectorFunction<T, boolean>;
declare const includesAsync: typeof containsAsync;

/**
 * Counts the number of elements in the source.
 * @param predicateFunction Predicate function to determine if an element should be counted.
 * @typeParam T Type of items in the source.
 * @returns Collector that counts the number of elements in the source.
 *
 * @example
 * ```typescript
 * const result = count<number>()([1, 2, 3]);
 * console.log(result); // 3
 * ```
 */
declare function count<T>(predicateFunction?: PredicateFunction<T>): CollectorFunction<T, number>;
declare const length: typeof count;

/** Returns the number of entries in the Iterable. */
declare function countAsync<T>(predicateFunction?: PredicateFunction<T>): AsyncCollectorFunction<T, number>;
declare const lengthAsync: typeof countAsync;

/**
 * Gets the element at the specified index.
 * @param index Index of the element to get.
 * @typeParam T Type of items in the source.
 * @returns Collector that gets the element at the specified index.
 *
 * @example
 * ```typescript
 * const result = elementAt<number>(1)([1, 2, 3]);
 * console.log(result); // 2
 * ```
 */
declare function elementAt<T>(index: number): CollectorFunction<T, T | undefined>;

/** Returns the nth entry from the Iterable. */
declare function elementAtAsync<T>(index: number): AsyncCollectorFunction<T, T | undefined>;

/**
 * Returns the first element in the source that satisfies the predicate.
 * @param predicate Predicate function to determine if an element should be returned.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the first element in the source that satisfies the predicate.
 *
 * @example
 * ```typescript
 * const result = first<number>((x) => x > 1)([1, 2, 3]);
 * console.log(result); // 2
 * ```
 */
declare function first<T>(predicate?: PredicateFunction<T>): CollectorFunction<T, T | undefined>;
declare const find: typeof first;

/** Returns the first entry from the Iterable that satisfy then 'predicate' function. */
declare function firstAsync<T>(predicate?: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, T | undefined>;
declare const findAsync: typeof firstAsync;

/**
 * Returns the index of the first element in the source that satisfies the predicate.
 * @param predicate Predicate function to determine if an element should be returned.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the index of the first element in the source that satisfies the predicate.
 *
 * @example
 * ```typescript
 * const result = firstIndex<number>((x) => x > 1)([1, 2, 3]);
 * console.log(result); // 1
 * ```
 */
declare function firstIndex<T>(predicate?: PredicateFunction<T>): CollectorFunction<T, number>;
declare const findIndex: typeof firstIndex;

/** Returns the index of the first entry from the Iterable that satisfy then 'predicate' function. */
declare function firstIndexAsync<T>(predicate?: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, number>;
declare const findIndexAsync: typeof firstIndexAsync;

/**
 * Returns the first element in the source that satisfies the predicate or a default value.
 * @param defaultValue Default value or factory to use if no element satisfies the predicate.
 * @param predicate Predicate function to determine if an element should be returned.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the first element in the source that satisfies the predicate or a default value.
 *
 * @example
 * ```typescript
 * const result = firstOrDefault<number>(0, (x) => x > 1)([1, 2, 3]);
 * console.log(result); // 2
 * ```
 */
declare function firstOrDefault<T>(defaultValue: ValueOrFactory<T>, predicate?: PredicateFunction<T>): CollectorFunction<T, T>;
declare const findOrDefault: typeof firstOrDefault;

/** Returns the first entry from the Iterable that satisfy then 'predicate' function or the 'defaultValue'. */
declare function firstOrDefaultAsync<T>(defaultValue: ValueOrFactory<T>, predicate?: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, T>;
declare const findOrDefaultAsync: typeof firstOrDefaultAsync;

/**
 * Executes a callback for each element in the source.
 * @param callback Callback function to execute for each element.
 * @typeParam T Type of items in the source.
 * @returns Collector that executes a callback for each element in the source.
 *
 * @example
 * ```typescript
 * forEach<number>((x) => console.log(x))([1, 2, 3]);
 * // 1
 * // 2
 * // 3
 * ```
 */
declare function forEach<T>(callback: CallbackFunction<T>): CollectorFunction<T, void>;

/** Call a callback function on every entry. */
declare function forEachAsync<T>(callback: MaybeAsyncCallbackFunction<T>): AsyncCollectorFunction<T, void>;

/**
 * Groups the source by a key selector.
 * @param keySelector Key selector function.
 * @typeParam T Type of items in the source.
 * @typeParam TKey Type of the key.
 * @returns Collector that groups the source by a key selector.
 *
 * @example
 * ```typescript
 * const result = groupBy<number, string>((x) => x % 2 === 0 ? "even" : "odd")([1, 2, 3, 4]);
 * console.log(result);
 * // Map {
 * //   'odd' => [1, 3],
 * //   'even' => [2, 4],
 * // }
 * ```
 */
declare function groupBy<T, TKey>(keySelector: (entry: T) => TKey): CollectorFunction<T, Map<TKey, T[]>>;

/** Creates a group of entries where the group key is calculated by the selector function. */
declare function groupByAsync<T, TKey>(keySelector: (entry: T) => TKey): AsyncCollectorFunction<T, Map<TKey, T[]>>;

/**
 * Groups the source by a key selector.
 * @param keySelector Key selector function.
 * @typeParam T Type of items in the source.
 * @typeParam TKey Type of the key.
 * @returns Collector that groups the source by a key selector.
 *
 * @example
 * ```typescript
 * const result = groupByRecord<number, string>((x) => x % 2 === 0 ? "even" : "odd")([1, 2, 3, 4]);
 * console.log(result);
 * // {
 * //   'odd': [1, 3],
 * //   'even': [2, 4],
 * // }
 * ```
 */
declare function groupByRecord<T, TKey extends string | number | symbol>(keySelector: (entry: T) => TKey): CollectorFunction<T, Record<TKey, T[]>>;
declare const group: typeof groupByRecord;

/** Creates a group of entries where the group key is calculated by the selector function. */
declare function groupByRecordAsync<T, TKey extends string | number | symbol>(keySelector: (entry: T) => TKey): AsyncCollectorFunction<T, Record<TKey, T[]>>;
declare const groupAsync: typeof groupByRecordAsync;

/**
 * Determines if the source is empty.
 * @typeParam T Type of items in the source.
 * @returns Collector that determines if the source is empty.
 *
 * @example
 * ```typescript
 * const result = isEmpty<number>()([1, 2, 3]);
 * console.log(result); // false
 * ```
 */
declare function isEmpty<T>(): CollectorFunction<T, boolean>;

/** Returns true if the AsyncIterable has 0 entry. */
declare function isEmptyAsync<T>(): AsyncCollectorFunction<T, boolean>;

/**
 * Joins the source into a string.
 * @param separator Separator between elements.
 * @typeParam T Type of items in the source.
 * @returns Collector that joins the source into a string.
 *
 * @example
 * ```typescript
 * const result = join<number>()([1, 2, 3]);
 * console.log(result); // "1,2,3"
 * ```
 */
declare function join<T>(separator?: string): CollectorFunction<T, string>;

/** Returns a string of all entries in the Iterable joined together seperated a given string. */
declare function joinAsync<T>(separator?: string): AsyncCollectorFunction<T, string>;

/**
 * Returns the last element in the source that satisfies the predicate.
 * @param predicate Predicate function to determine if an element should be returned.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the last element in the source that satisfies the predicate.
 *
 * @example
 * ```typescript
 * const result = last<number>((x) => x > 1)([1, 2, 3]);
 * console.log(result); // 3
 * ```
 */
declare function last<T>(predicate?: PredicateFunction<T>): CollectorFunction<T, T | undefined>;
declare const findLast: typeof last;

/** Returns the last entry from the Iterable that satisfy then 'predicate' function. */
declare function lastAsync<T>(predicate?: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, T | undefined>;
declare const findLastAsync: typeof lastAsync;

/**
 * Returns the index of the last element in the source that satisfies the predicate.
 * @param predicate Predicate function to determine if an element should be returned.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the index of the last element in the source that satisfies the predicate.
 *
 * @example
 * ```typescript
 * const result = lastIndex<number>((x) => x > 1)([1, 2, 3]);
 * console.log(result); // 2
 * ```
 */
declare function lastIndex<T>(predicate?: PredicateFunction<T>): CollectorFunction<T, number>;
declare const findLastIndex: typeof lastIndex;

/** Returns the index of the last entry from the Iterable that satisfy then 'predicate' function. */
declare function lastIndexAsync<T>(predicate?: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, number>;
declare const findLastIndexAsync: typeof lastIndexAsync;

/**
 * Returns the last element in the source that satisfies the predicate or a default value if no such element is found.
 * @param defaultValue Default value to return if no element is found.
 * @param predicate Predicate function to determine if an element should be returned.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the last element in the source that satisfies the predicate or a default value if no such element is found.
 *
 * @example
 * ```typescript
 * const result = lastOrDefault<number>(0, (x) => x > 1)([1, 2, 3]);
 * console.log(result); // 3
 * ```
 */
declare function lastOrDefault<T>(defaultValue: ValueOrFactory<T>, predicate?: PredicateFunction<T>): CollectorFunction<T, T | undefined>;
declare const findLastOrDefault: typeof lastOrDefault;

/** Returns the last entry from the Iterable that satisfy then 'predicate' function. */
declare function lastOrDefaultAsync<T>(defaultValue: ValueOrFactory<T>, predicate?: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, T | undefined>;
declare const findLastOrDefaultAsync: typeof lastOrDefaultAsync;

/**
 * Returns the maximum value in a sequence of numbers.
 * @param numbers Sequence of numbers to find the maximum value.
 * @returns Maximum value in the sequence.
 *
 * @example
 * ```typescript
 * const result = max([1, 2, 3]);
 * console.log(result); // 3
 * ```
 */
declare const max: CollectorFunction<number, number | undefined>;

/** Return the largest value of all entries in the Iterable */
declare const maxAsync: AsyncCollectorFunction<number, number | undefined>;

/**
 * Returns the element in the source that has the maximum value according to the comparer.
 * @param comparer Comparer function to determine the maximum value.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the element in the source that has the maximum value according to the comparer.
 *
 * @example
 * ```typescript
 * const result = maxBy<number>((a, b) => a - b)([1, 2, 3]);
 * console.log(result); // 3
 * ```
 */
declare function maxBy<T>(comparer: CompareFunction<T>): CollectorFunction<T, T | undefined>;

/** Return the largest value of all entries in the Iterable based on the comparer function */
declare function maxByAsync<T>(comparer: CompareFunction<T>): AsyncCollectorFunction<T, T | undefined>;

/**
 * Returns the minimum value in a sequence of numbers.
 * @param numbers Sequence of numbers to find the minimum value.
 * @returns Minimum value in the sequence.
 *
 * @example
 * ```typescript
 * const result = min([1, 2, 3]);
 * console.log(result); // 1
 * ```
 */
declare const min: CollectorFunction<number, number | undefined>;

/** Return the smallest value of all entries in the Iterable */
declare const minAsync: AsyncCollectorFunction<number, number | undefined>;

/**
 * Returns the element in the source that has the minimum value according to the comparer.
 * @param comparer Comparer function to determine the minimum value.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the element in the source that has the minimum value according to the comparer.
 *
 * @example
 * ```typescript
 * const result = minBy<number>((a, b) => a - b)([1, 2, 3]);
 * console.log(result); // 1
 * ```
 */
declare function minBy<T>(comparer: CompareFunction<T>): CollectorFunction<T, T | undefined>;

/** Return the smallest value of all entries in the Iterable based on the comparer function */
declare function minByAsync<T>(comparer: CompareFunction<T>): AsyncCollectorFunction<T, T | undefined>;

declare function partition<T>(predicate: PredicateFunction<T>): CollectorFunction<T, [T[], T[]]>;

declare function partitionAsync<T>(predicate: MaybeAsyncPredicateFunction<T>): AsyncCollectorFunction<T, [T[], T[]]>;

/**
 * Returns the result of applying the reducer function to each element of the source.
 * @param reducerFunction Reducer function to apply to each element.
 * @param initialValue Initial value or factory function to use as the first argument to the reducer function.
 * @typeParam T Type of items in the source.
 * @typeParam O Type of the result.
 * @returns Collector that returns the result of applying the reducer function to each element of the source.
 *
 * @example
 * ```typescript
 * const result = reduce<number, number>((prev, curr) => prev + curr, 0)([1, 2, 3]);
 * console.log(result); // 6
 * ```
 */
declare function reduce<T, O>(reducerFunction: ReduceFunction<T, O>, initialValue: ValueOrFactory<O>): CollectorFunction<T, O>;

/** Executes a reducer function on each entry of the Iterable, resulting in a single output value. */
declare function reduceAsync<T, O>(reducerFunction: AsyncReduceFunction<T, O>, initialValue: ValueOrFactory<O>): AsyncCollectorFunction<T, O>;

/**
 * Determines whether two sequences are equal by comparing the elements pairwise.
 * @param other Iterable to compare to the source.
 * @param equalsFunction Function to determine if two elements are equal.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns true if the two sequences are equal, false otherwise.
 *
 * @example
 * ```typescript
 * const result = sequenceEquals([1, 2, 3])([1, 2, 3]);
 * console.log(result); // true
 * ```
 */
declare function sequenceEquals<T>(other: Iterable<T>, equalsFunction?: EqualsFunction<T>): CollectorFunction<T, boolean>;

declare function sequenceEqualsAsync<T>(other: Iterable<T>, equalsFunction?: EqualsFunction<T>): AsyncCollectorFunction<T, boolean>;

/**
 * Returns the sum of the source.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the sum of the source.
 *
 * @example
 * ```typescript
 * const result = sum<number>()([1, 2, 3]);
 * console.log(result); // 6
 * ```
 */
declare function sum(): CollectorFunction<number, number | undefined>;

/** Return the sum of all entries in the Iterable */
declare function sumAsync(): AsyncCollectorFunction<number, number | undefined>;

/**
 * Returns the source as an array.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the source as an array.
 *
 * @example
 * ```typescript
 * const result = toArray<number>()([1, 2, 3]);
 * console.log(result); // [1, 2, 3]
 * ```
 */
declare function toArray<T>(): CollectorFunction<T, T[]>;

/** Creates an Array from an Iterable */
declare function toArrayAsync<T>(): AsyncCollectorFunction<T, T[]>;

/**
 * Converts the source to a map.
 * @param keySelector Key selector function.
 * @param valueSelector Value selector function.
 * @typeParam T Type of items in the source.
 * @typeParam TKey Type of the key.
 * @typeParam TValue Type of the value.
 * @returns Collector that converts the source to a map.
 *
 * @example
 * ```typescript
 * const result = toMap<number, string, number>((x) => x.toString(), (x) => x * 2)([1, 2, 3]);
 * console.log(result);
 * // Map {
 * //   '1' => 2,
 * //   '2' => 4,
 * //   '3' => 6,
 * // }
 * ```
 */
declare function toMap<T, TKey, TValue>(keySelector: (entry: T) => TKey, valueSelector: (entry: T) => TValue): CollectorFunction<T, Map<TKey, TValue>>;

/** Creates a Map from an Iterable */
declare function toMapAsync<T, TKey, TValue>(keySelector: (entry: T) => TKey, valueSelector: (entry: T) => TValue): AsyncCollectorFunction<T, Map<TKey, TValue>>;

/**
 * Converts the source to a record.
 * @param keySelector Key selector function.
 * @param valueSelector Value selector function.
 * @typeParam T Type of items in the source.
 * @typeParam TKey Type of the key.
 * @typeParam TValue Type of the value.
 * @returns Collector that converts the source to a record.
 *
 * @example
 * ```typescript
 * const result = toRecord<number, string, number>((x) => x.toString(), (x) => x * 2)([1, 2, 3]);
 * console.log(result);
 * // {
 * //   '1': 2,
 * //   '2': 4,
 * //   '3': 6,
 * // }
 * ```
 */
declare function toRecord<T, TKey extends string | number | symbol, TValue>(keySelector: (entry: T) => TKey, valueSelector: (entry: T) => TValue): CollectorFunction<T, Record<TKey, TValue>>;
declare const toObject: typeof toRecord;

/** Creates a Map from an Iterable */
declare function toRecordAsync<T, TKey extends string | number | symbol, TValue>(keySelector: (entry: T) => TKey, valueSelector: (entry: T) => TValue): AsyncCollectorFunction<T, Record<TKey, TValue>>;
declare const toObjectAsync: typeof toRecordAsync;

/**
 * Returns the source as a set.
 * @typeParam T Type of items in the source.
 * @returns Collector that returns the source as a set.
 *
 * @example
 * ```typescript
 * const result = toSet<number>()([1, 2, 3]);
 * console.log(result); // Set { 1, 2, 3 }
 * ```
 */
declare function toSet<T>(): CollectorFunction<T, Set<T>>;

/** Creates a Set from an Iterable */
declare function toSetAsync<T>(): AsyncCollectorFunction<T, Set<T>>;

export { type AsyncCollectorFunction, type AsyncMapperFunction, type AsyncOperationFunction, type AsyncReduceFunction, AsyncStream, type CallbackFunction, type CollectorFunction, type CompareFunction, type EqualsFunction, type MapperFunction, type MaybeAsyncCallbackFunction, type MaybeAsyncPredicateFunction, type MaybeAsyncValue, type OperationFunction, type PredicateFunction, type ReduceFunction, Stream, type TypeGuardFunction, type ValueOrFactory, all, allAsync, any, anyAsync, appendWith, appendWithAsync, arrayFilter, arrayMap, buffer, bufferAsync, chain, chainAsync, compound, compoundAsync, concat, concatAsync, concatWith, concatWithAsync, contains, containsAsync, count, countAsync, cycle, defaultIfEmpty, defaultIfEmptyAsync, distinct, distinctAsync, distinctBy, distinctByAsync, distinctUntilChanged, distinctUntilChangedAsync, distinctUntilKeyChanged, distinctUntilKeyChangedAsync, elementAt, elementAtAsync, empty, endWith, endWithAsync, every, everyAsync, falsy, falsyAsync, filter, filterAsync, find, findAsync, findIndex, findIndexAsync, findLast, findLastAsync, findLastIndex, findLastIndexAsync, findLastOrDefault, findLastOrDefaultAsync, findOrDefault, findOrDefaultAsync, first, firstAsync, firstIndex, firstIndexAsync, firstOrDefault, firstOrDefaultAsync, flat, flatAsync, flatMap, flatMapAsync, flatten, flattenAsync, forEach, forEachAsync, from, fromAsync, group, groupAsync, groupBy, groupByAsync, groupByRecord, groupByRecordAsync, includes, includesAsync, isEmpty, isEmptyAsync, isFunction, isIterable, isNotNull, isNotNullOrEmpty, isNotNullOrWhitespace, join, joinAsync, last, lastAsync, lastIndex, lastIndexAsync, lastOrDefault, lastOrDefaultAsync, length, lengthAsync, map, mapAsync, max, maxAsync, maxBy, maxByAsync, min, minAsync, minBy, minByAsync, noop, noopAsync, notNullOrEmpty, notNullOrEmptyAsync, notNullOrWhitespace, notNullOrWhitespaceAsync, of, ofType, ofTypeAsync, pairwise, pairwiseAsync, partition, partitionAsync, pipe, pipeAsync, product, range, reduce, reduceAsync, repeat, sequenceEquals, sequenceEqualsAsync, skip, skipAsync, skipWhile, skipWhileAsync, some, someAsync, startWith, startWithAsync, stream, streamAsync, streamOf, sum, sumAsync, take, takeAsync, takeWhile, takeWhileAsync, tap, tapAsync, toArray, toArrayAsync, toMap, toMapAsync, toObject, toObjectAsync, toRecord, toRecordAsync, toSet, toSetAsync, truthy, truthyAsync, zip, zipAsync, zipLongest };
