iterator-helper
Provide helpers that polyfill all methods defined in iterator helpers proposal, both for Iterator
and AsyncIterator
, and even more.
Installation
Install it with npm/yarn/what you want.
npm i iterator-helper
Getting started
You can wrap an iterable or an iterator with the exported iter
(for standard iterables) and aiter
(for async iterables) functions.
import { iter, aiter } from 'iterator-helper';
const iterator = iter([1, 2, 3]);
const mapped_cycle = iterator
.cycle()
.map(e => e * 2)
.asIndexedPairs();
for (const [index, element] of mapped_cycle) {
console.log(index, element);
}
You can also extend two exported classes, HIterator
and HAsyncIterator
(those names are used to avoid conflicts with possible futures Iterator
and AsyncIterator
global objects), in order to make your classes iterables.
import { HIterator } from 'iterator-helper';
class RangeIterator extends HIterator {
constructor(start, stop = undefined, step = 1) {
super();
this.position = stop === undefined ? 0 : start;
this.stop = stop === undefined ? start : stop;
this.step = step;
if (stop < start) {
throw new Error('Stop cannot be inferior to start.');
}
if (step <= 0) {
throw new Error('Step must be superior to 0.');
}
}
next() {
if (this.position < this.stop) {
const current = this.position;
this.position += this.step;
return { value: current, done: false };
}
return { value: undefined, done: true };
}
}
const range = new RangeIterator(10).filter(e => e % 2 === 0);
range.next();
range.next();
range.next();
API
As the proposal purpose, there are a few methods for each prototype. They're presented here with TypeScript types.
interface HIterator<T, TReturn = any, TNext = undefined> {
map<R>(callback: (value: T) => R) : HIterator<R, TReturn, TNext>;
filter(callback: (value: T) => boolean) : HIterator<T, TReturn, TNext>;
take(limit: number) : HIterator<T, TReturn, TNext>;
drop(limit: number) : HIterator<T, TReturn, TNext>;
asIndexedPairs() : HIterator<[number, T], TReturn, TNext>;
flatMap<R>(mapper: (value: T) => Iterator<R> | R) : HIterator<R, TReturn, TNext>;
find(callback: (value: T) => boolean) : T | undefined;
every(callback: (value: T) => boolean) : boolean;
some(callback: (value: T) => boolean) : boolean;
toArray(max_count?: number) : T[];
reduce<V>(reducer: (acc: V, value: T) => V, initial_value?: V) : V;
forEach(callback: (value: T) => any) : void;
count() : number;
join(glue: string) : string;
chain<I>(...iterables: IterableIterator<I>[]) : HIterator<T | I>;
zip<O>(...others: IterableIterator<O>[]) : HIterator<(T | O)[]>;
takeWhile(callback: (value: T) => boolean) : HIterator<T>;
dropWhile(callback: (value: T) => boolean) : HIterator<T>;
fuse() : HIterator<T>;
partition(callback: (value: T) => boolean) : [T[], T[]];
findIndex(callback: (value: T) => boolean) : number;
max() : number;
min() : number;
cycle() : HIterator<T>;
groupBy<K extends string | number | symbol>(callback: (value: T) => K) : { [Key in K]: T[] };
toIndexedItems<K>(keyGetter: (value: T) => K) : Map<K, T>;
intersection<O>(otherItems: IteratorOrIterable<O>, isSameItemCallback: (value: T, other: O) => boolean = Object.is) : HIterator<T>;
difference<O>(otherItems: IteratorOrIterable<O>, isSameItemCallback: (value: T, other: O) => boolean = Object.is) : HIterator<T>;
symmetricDifference<O>(otherItems: IteratorOrIterable<O>, isSameItemCallback: (value: T, other: O) => boolean = Object.is) : HIterator<T>;
toAsyncIterator(): HAsyncIterator<T>;
}
interface HAsyncIterator<T, TReturn = any, TNext = undefined> {
map<R>(callback: (value: T) => R) : HAsyncIterator<R, TReturn, TNext>;
filter(callback: (value: T) => boolean) : HAsyncIterator<T, TReturn, TNext>;
take(limit: number) : HAsyncIterator<T, TReturn, TNext>;
drop(limit: number) : HAsyncIterator<T, TReturn, TNext>;
asIndexedPairs() : HAsyncIterator<[number, T], TReturn, TNext>;
flatMap<R>(mapper: (value: T) => AsyncIterator<R> | R) : HAsyncIterator<R, TReturn, TNext>;
find(callback: (value: T) => boolean) : Promise<T | undefined>;
every(callback: (value: T) => boolean) : Promise<boolean>;
some(callback: (value: T) => boolean) : Promise<boolean>;
toArray(max_count?: number) : Promise<T[]>;
reduce<V>(reducer: (acc: V, value: T) => V, initial_value?: V) : Promise<V>;
forEach(callback: (value: T) => any) : Promise<void>;
count() : Promise<number>;
join(glue: string) : Promise<string>;
chain<I>(...iterables: IterableIterator<I>[]) : HAsyncIterator<T | I>;
zip<O>(...others: IterableIterator<O>[]) : HAsyncIterator<(T | O)[]>;
takeWhile(callback: (value: T) => boolean) : HAsyncIterator<T>;
dropWhile(callback: (value: T) => boolean) : HAsyncIterator<T>;
fuse() : HAsyncIterator<T>;
partition(callback: (value: T) => boolean) : Promise<[T[], T[]]>;
findIndex(callback: (value: T) => boolean) : Promise<number>;
max() : Promise<number>;
min() : Promise<number>;
cycle() : HAsyncIterator<T>;
groupBy<K extends string | number | symbol>(callback: (value: T) => K | PromiseLike<K>) : Promise<{ [Key in K]: T[] }>;
toIndexedItems<K>(keyGetter: (value: T) => K | PromiseLike<K>) : Promise<Map<K, T>>;
intersection<O>(
otherItems: AsyncIteratorOrIterable<O>,
isSameItemCallback: (value: T, other: O) => boolean | PromiseLike<boolean> = Object.is
) : HAsyncIterator<T>;
difference<O>(
otherItems: AsyncIteratorOrIterable<O>,
isSameItemCallback: (value: T, other: O) => boolean | PromiseLike<boolean> = Object.is
) : HAsyncIterator<T>;
symmetricDifference<O>(
otherItems: AsyncIteratorOrIterable<O>,
isSameItemCallback: (value: T, other: O) => boolean | PromiseLike<boolean> = Object.is
) : HAsyncIterator<T>;
}
Helpers
iter
function expose some iterator creator helpers:
There's presented as TypeScript types.
interface IIterFunction {
range(stop: number): HIterator<number>;
range(start: number, stop: number): HIterator<number>;
range(start: number, stop: number, step: number): HIterator<number>;
repeat<I>(item: I): HIterator<I>;
repeat<I>(item: I, times: number): HIterator<I>;
}
Example
for (const i of iter.range(10)) {
}
for (const _ of iter.repeat(null, 10)) {
}
iter.repeat({ id: 1, name: 'Sialae' })
.asIndexedPairs()
.map(([index, item]) => ({ ...item, id: index + 1 }))
.filter(item => item.id % 2 !== 0)
.take(3)
.toArray();