UNPKG

@drew887121/iteratorfuncs

Version:

A small package to make working with iterators easier

186 lines (174 loc) 9.38 kB
/** * IteratorFuncs a simple single file package to make working with JS iterators easier. * * The documentation lives online [here](https://drew887.github.io/iteratorFuncs/modules.html). * * If you've ever had a generator, or a Set, or a Map that you've needed to map/filter/reduce over in JS, you've been hit * by the pain of having to either convert to an Array with `Array.from` and then use the method you need, or write a * for...of loop and do your logic in there. * * While the for...of loop is almost certainly the "proper" or "js way" of doing things, and is what you normally get as * an answer when searching for this, it can be a little disappointing or jarring for those of us wanting a more fp like * approach that js normally lets you take. * * So this package is simply to help facilitate these patterns for IterableIterators. * * tldr: ```typescript const set = new Set([1, 2, 3, 4, 5]); const mappedAndFiltered = mapIterator(set, (item) => item * 2) .filter((item) => item > 5); console.log(Array.from(mappedAndFiltered)); // logs out [6, 8, 10] ``` * * @packageDocumentation */ /** * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * We override the default Iterable interface since it doesn't allow forwarding of the other 2 type params that Iterator can take */ export interface Iterable<TValue, TReturn = any, TNext = any> { [Symbol.iterator](): Iterator<TValue, TReturn, TNext>; } /** * We override the default IterableIterator interface since it doesn't allow forwarding of the other 2 type params that Iterator can take */ export interface IterableIterator<TValue, TReturn = any, TNext = any> extends Iterator<TValue, TReturn, TNext> { [Symbol.iterator](): IterableIterator<TValue, TReturn, TNext>; } /** * Type alias to simplify this union * TODO: Come up with a better name */ export type IteratorArg<TIteratorValue, TIteratorReturn, TIteratorNext> = Iterable<TIteratorValue, TIteratorReturn, TIteratorNext> | IterableIterator<TIteratorValue, TIteratorReturn, TIteratorNext>; /** * An AugmentedIterator represents one of the IterableIterators we return. * This abstract class is exported only to provide type/intellisense information, * and should be only implemented internally. */ export declare abstract class AugmentedIterator<TValue, TReturn = any, TNext = any> implements IterableIterator<TValue, TReturn, TNext> { [Symbol.iterator](): this; abstract next(...args: [] | [TNext]): IteratorResult<TValue, TReturn>; map<TMapperReturn>(mapper: (item: TValue) => TMapperReturn): AugmentedIterator<TMapperReturn, TReturn, TNext>; filter(filter: (item: TValue) => boolean): AugmentedIterator<TValue, TReturn, TNext>; reduce<TReducerReturn>(reducer: (carry: TReducerReturn, item: TValue) => TReducerReturn, initial: TReducerReturn): AugmentedIterator<TReducerReturn, TReturn, TNext>; } /** * Given an Iterable or IterableIterator, a reducer, and an initial value, return a new IterableIterator that yields * values that are automatically piped through said reducer. * @param {Iterable} iterator - The iterator you wish to reduce over * @param {Function} reducer - A function to use to reduce the elements iterator produces * @param initial The initial value to pass to reducer with the first element * @typeParam TValue - The value returned from the iterator * @typeParam TReducerReturn - The return type of your reducer function * @typeParam TReturn - If your iterator has a return type it must be the same as TIteratorValue, otherwise undefined * @typeParam TNext - The type your iterator is expecting as what's passed to its next function. For generators this is the type returned after a yield. * * @example const set: Set<number> = new Set([1, 2, 3, 4, 5]); const summingIterator = reduceIterator( set.values(), (carry: number, item: number): number => { return carry + item; }, 0, ); // summingIterator will now yield the sum for each value seen thus far const finalValues = Array.from(summingIterator); // finalValues will now be [1,3,6,10,15]; */ export declare function reduceIterator<TValue, TReducerReturn, TReturn = TValue | undefined, TNext = any>(iterator: IteratorArg<TValue, TReturn, TNext>, reducer: (carry: TReducerReturn, arg: TValue) => TReducerReturn, initial: TReducerReturn): AugmentedIterator<TReducerReturn, TReturn, TNext>; /** * Given an IteratorArg and a mapping function, returns a new IterableIterator that yields values from the initial iterator * but passed through the mapping function. * @param {Iterable} iterator - The iterator you wish to map elements from * @param {Function} mapper - A function to use to map the elements iterator produces * @typeParam TValue - The value returned from the iterator * @typeParam TMapperReturn - The return type of your reducer function * @typeParam TReturn - If your iterator has a return type it must be the same as TIteratorValue, otherwise undefined * @typeParam TNext - The type your iterator is expecting as what's passed to its next function. For generators this is the type returned after a yield. * @example const set = new Set([1, 2, 3, 4, 5]); const mapped = mapIterator(set, (item) => item * 2); console.log(Array.from(mapped)); // logs out [2, 4, 6, 8, 10] */ export declare function mapIterator<TValue, TMapperReturn, TReturn = TValue | undefined, TNext = any>(iterator: IteratorArg<TValue, TReturn, TNext>, mapper: (arg: TValue) => TMapperReturn): AugmentedIterator<TMapperReturn, TReturn, TNext>; /** * Given an IteratorArg and a filtering function it will return a new IterableIterator that when polled will eagerly pull * values from iterator and pass them to filterer until filterer returns true for an item, or we reach the end of iterator; * it will then yield this value itself. * * **NOTE:** if iterator relies on values being passed to next, the returned IterableIterator will re-use the same next * until a value passes the filterer. * value until an item is raised that passes the filterer. This can lead to strange behaviours. * @param {Iterable} iterator - The iterator you wish to map elements from * @param {Function} filterer - Only values for which this function returns true are yielded. * @typeParam TValue - The value returned from the iterator * @typeParam TReturn - If your iterator has a return type it must be the same as TIteratorValue, otherwise undefined * @typeParam TNext - The type your iterator is expecting as what's passed to its next function. For generators this is the type returned after a yield. * * @example const set = new Set([1, 2, 3, 4, 5]); const filtered = filterIterator(set, (item) => item % 2 === 0); console.log(Array.from(filtered)); // logs out [2, 4] */ export declare function filterIterator<TValue, TReturn = TValue | undefined, TNext = any>(iterator: IteratorArg<TValue, TReturn, TNext>, filterer: (arg: TValue) => boolean): AugmentedIterator<TValue, TReturn, TNext>; /** * Given an iterator, eagerly reduce over its results until it finishes and return the result * @param {Iterable} iterator - The iterator you wish to reduce over * @param {Function} reducer - A function to use to reduce the elements iterator produces * @param initial The initial value to pass to reducer with the first element. Also returned if iterator never yields a value * @typeParam TValue - The type of values that iterator will yield and that initial must be * @typeParam TReturn - The type of values that reducer will return * * @example const set: Set<number> = new Set([1, 2, 3, 4, 5]); const sum = eagerlyReduceIterator( set.values(), (carry: number, item: number): number => { return carry + item; }, 0, ); // sum is now 15 */ export declare function eagerlyReduceIterator<TValue, TReturn>(iterator: Iterable<TValue>, reducer: (carry: TReturn, arg: TValue) => TReturn, initial: TReturn): TReturn; /** * Eagerly Map over an iterator and return an array of results * @param {Iterable} iterator - The iterator you wish to map over * @param {Function} mapper - The function you want to use to process any elements yielded from iterator * @typeParam TValue - The type of values that iterator will yield * @typeParam TReturn - The type of values that mapper will return * * @example const set: Set<number> = new Set([1, 2, 3, 4, 5]); const squaredValues = mapIteratorToArray( set.values(), (item: number): number => { return item * item; }, ); */ export declare function mapIteratorToArray<TValue, TReturn>(iterator: Iterable<TValue>, mapper: (arg: TValue) => TReturn): Array<TReturn>; /** * Eagerly Filter over an iterator and return an array of results * @param {Iterable} iterator - The iterator you wish to filter over * @param {Function} filter - Your filtering function * @typeParam TValue - The type of values that iterator will yield * * @example const set: Set<number> = new Set([1, 2, 3, 4, 5]); const evenValues = filterIteratorToArray( set.values(), (item: number): boolean => { return item % 2 === 0; }, ); // evenValues = [2, 4]; */ export declare function filterIteratorToArray<TValue>(iterator: Iterable<TValue>, filter: (arg: TValue) => boolean): Array<TValue>;