An iterable with array-like methods with lazy evaluation, both sync and async iteration, and support for sync and async callbacks.
ExtendedIterable accepts any iterator, iterable, or generator:
import ExtendedIterable from 'extended-iterable';
const extendedIterable = new ExtendedIterable([1, 2, 3]);
for (const value of extendedIterable) {
	console.log(value);
}You can chain methods together:
const listing = fs.readdirSync('.', { withFileTypes: true });
const directories = new ExtendedIterable(listing)
	.filter(file => file.isDirectory())
	.map(file => file.name);
for (const dir of directories) {
	console.log(dir);
}To convert the results to an array:
// sync only
const arr = Array.from(extendedIterable);
// both sync and async
const arr2 = await extendedIterable.asArray;An async iterator with an async callback:
import { readdir, readFile } from 'node:fs/promises';
async function* getDirectoryListing() {
	const entries = await readdir('.', { withFileTypes: true });
	for (const entry of entries) {
		yield entry;
	}
}
const sourceFiles = new ExtendedIterable(getDirectoryListing)
	.filter(file => file.isFile() && file.name.endsWith('.js'))
	.map(async file => ({
		name: file.name,
		contents: await readFile(file.name, 'utf-8')
	}));
for await (const src of sourceFiles) {
	console.log(`${src.name} is ${src.contents.length} bytes`);
}Creates an iterable from an array-like object, iterator, async iterator, iterable, generator, or async generator.
- iterator:- IterableLike<T>- An array-like object, iterator, async iterator, iterable, generator or async generator.
// array
new ExtendedIterable([1, 2, 3])
// string
new ExtendedIterable('Hello World!');
// Set
new ExtendedIterable(new Set([1, 2, 3]));
// iterable object
new ExtendedIterable({
	index: 0,
	next() {
		if (this.index > 3) {
			return { done: true, value: undefined };
		}
		return { done: false, value: this.index++ };
	}
});
// generator
new ExtendedIterable(function* () {
	yield 1;
	yield 2;
	yield 3;
});
// async generator
new ExtendedIterable(async function* () {
	yield 1;
	yield 2;
	yield 3;
});The ExtendedIterable is a generic class and the data type can be explicitly
specified:
new ExtendedIterable([1, 2, 3]);- Array<T>|- Promise<Array<T>>- An array or a promise that resolves an array.
const iterator = new ExtendedIterable([1, 2, 3]);
const arr = iterator.asArray;If the iterator is async or any array-like functions have an async callback, it will return a promise.
const iter = new ExtendedIterable(async function* () {
	yield 1;
	yield 2;
	yield 3;
});
const arr = await iter.map(async value => value).asArray;Returns the item or a promise that resolves an item at the given index. If the
index is less than 0, an error is thrown. If the index is greater than the
number of items in the iterator, undefined is returned.
- index:- number- The index of the item to return.
- T | Promise<T> | undefined | Promise<undefined>- The item at the specified index. Value
const iterator = new ExtendedIterable([1, 2, 3]);
const value = iterator.at(2); // 3Concatenates the iterable with another iterable.
- iterator:- IterableLike<T>- An array-like object, iterator, async iterator, iterable, generator or async generator.
- ExtendedIterable<T>The concatenated iterable.
const iterator = new ExtendedIterable([1, 2, 3]);
const concatenated = iterator.concat([4, 5, 6]);
console.log(concatenated.asArray); // [1, 2, 3, 4, 5, 6]Returns a new iterable skipping the first count items.
- count: number- The number of items to skip.
- ExtendedIterable<T>- The new iterable.
const iterator = new ExtendedIterable([1, 2, 3, 4]).drop(2);
console.log(iterator.asArray); // [3, 4]Returns true if the callback returns true for every item of the iterable.
- callback: (value: T, index: number) => boolean | Promise<boolean>- The callback function to call for each result.
- boolean | Promise<boolean>- Returns or resolves- trueif the callback returns- truefor every item of the iterable.
const iterator = new ExtendedIterable([1, 2, 3]);
const isAllValid = iterator.every(item => item > 0);Async callbacks are supported, but you must await the iterator:
const iterator = new ExtendedIterable([1, 2, 3]);
const isAllValid = await iterator.every(async item => item > 0);Returns a new iterable containing only the values for which the callback
returns true.
- callback: (value: T, index: number) => boolean | Promise<boolean>- The callback function to call for each result.
- ExtendedIterable<T>- The new iterable.
const iterator = new ExtendedIterable([1, 2, 3]);
const evenIterator = iterator.filter((item) => {
	return item % 2 === 0;
});
console.log(evenIterator.asArray); // [2]Returns the first item of the iterable for which the callback returns true.
- callback:- (value: T, index: number) => boolean | Promise<boolean>- The callback function to call for each result.
- T | Promise<T> | undefined | Promise<undefined>- The first item of the iterable for which the callback returns or resolves- true, or- undefinedif no such item is found.
const iterator = new ExtendedIterable([1, 2, 3]);
const found = iterator.find(item => item === 2);Returns a new iterable with the flattened results of a callback function.
- callback:- (value: T, index: number) => U | U[] | Iterable<U> | Promise<U | U[] | Iterable<U>>- The callback function to call for each result.
- ExtendedIterable<U>- The new iterable with the values flattened.
const iterator = new ExtendedIterable([1, 2, 3]);
const flattened = iterator.flatMap(item => [item, item]);
console.log(flattened.asArray); // [1, 1, 2, 2, 3, 3]Calls a function for each item of the iterable.
- callback:- (value: T, index: number) => boolean | Promise<boolean>- The callback function to call for each result.
- void | Promise<void>- Returns nothing or a promise that resolves nothing.
const iterator = new ExtendedIterable([1, 2, 3]);
iterator.forEach(item => console.log(item)); // 1, 2, 3Returns a new iterable with the results of calling a callback function.
- callback:- (value: T, index: number) => boolean | Promise<boolean>- The callback function to call for each result.
- ExtendedIterable<T>- The new iterable with the mapped values.
const iterator = new ExtendedIterable([1, 2, 3]);
const mapped = iterator.map(item => item * 2);
console.log(mapped.asArray); // [2, 4, 6]Catch errors thrown during iteration and allow iteration to continue. This
method is most useful for methods that return an iterable such as drop(),
filter(), flatMap(), map(), reduce(), and take().
- catchCallback:- (error: Error) => Error | Promise<Error>- The callback to handle errors. The returned error is logged/handled but iteration continues.
- ExtendedIterable<T | Error>- The new iterable.
const iterator = new ExtendedIterable([1, 2, 3]);
const mapped = iterator
	.map(item => {
		if (item % 2 === 0) {
			throw new Error('Even');
		}
		return 'odd';
	})
	.mapError();
console.log(mapped.asArray); // ['odd', Error('Even'), 'odd']Reduces the iterable to a single value.
- callback:- (previousValue: U, currentValue: T, currentIndex: number) => U | Promise<U>- The callback function to call for each result.
- initialValue:- U[optional] - The initial value to use for the accumulator.
- U | Promise<U>- Returns or resolves the reduced value.
const iterator = new ExtendedIterable([1, 2, 3]);
const sum = iterator.reduce((acc, item) => acc + item, 0);
console.log(sum); // 6Returns a new iterable with the items between the start and end indices. If
start or end are less than zero, an error is thrown. If start is greater
than end, an empty iterator is returned.
- start:- number | undefined[optional] - The index to start at. Defaults to- 0, the first item.
- end:- number | undefined[optional] - The index to end at. Defaults to the last item.
- ExtendedIterable<T>- The new iterable with the sliced range.
const iterator = new ExtendedIterable([1, 2, 3, 4, 5]);
const sliced = iterator.slice(2, 4);
console.log(sliced.asArray); // [3, 4]Returns true if the callback returns true for any item of the iterable.
- callback:- (value: T, index: number) => boolean | Promise<boolean>- The callback function to call for each result.
- boolean | Promise<boolean>-- trueif the callback returns- truefor any item of the iterable,- falseotherwise.
const iterator = new ExtendedIterable([1, 2, 3]);
const hasEven = iterator.some(item => item % 2 === 0);
console.log(hasEven); // trueReturns a new iterable with the first limit items. If limit is less than
zero, an error is thrown. If the limit is greater than the number of items in
the iterable, all items are returned.
- limit:- number- The number of items to take.
- ExtendedIterable<T>- The new iterable with the first- limititems.
const iterator = new ExtendedIterable([1, 2, 3]);
const taken = iterator.take(2);
console.log(taken.asArray); // [1, 2]A static method for convenience that returns an array or a promise that resolves an array.
- iterator:- IterableLike<T>- An array-like object, iterator, async iterator, iterable, generator or async generator.
- Array<T> | Promise<Array<T>>- An array of all items in the iterator.
const arr = ExtendedIterable.from(new Set([1, 2, 3]));
console.log(arr); // [1, 2, 3]- Array<T>|- Promise<Array<T>>- An array or a promise that resolves an array.
const iterator = new ExtendedIterable([1, 2, 3]);
const arr = iterator.toArray();If the iterator is async or any array-like functions have an async callback, it will return a promise.
const iter = new ExtendedIterable(async function* () {
	yield 1;
	yield 2;
	yield 3;
});
const arr = await iter.map(async value => value).toArray();Anything that can be iterated. This includes types such as Map and Set as
well as plain strings.
type IterableLike<T> =
	| Iterator<T>
	| AsyncIterator<T>
	| Iterable<T>
	| (() => Generator<T>)
	| (() => AsyncGenerator<T>);This library is licensed under the terms of the MIT license.