Minimal zero-dependency utilities for using JavaScript Iterables in all environments.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core synchronous iteration functionality for working with Iterables, Array-like objects, and testing for iteration support. These utilities enable libraries to accept multiple collection types with consistent behavior across all JavaScript environments.
Symbol used as the property name for iterator methods. Represents Symbol.iterator when available, falls back to "@@iterator" for legacy environments.
/**
* Property name for iterator method, used for creating new Iterables
* @type {Symbol|string}
*/
export const $$iterator: unique symbol;Usage Example:
import { $$iterator } from "iterall";
function Counter(to) {
this.to = to;
}
Counter.prototype[$$iterator] = function() {
return {
to: this.to,
num: 0,
next() {
if (this.num >= this.to) {
return { value: undefined, done: true };
}
return { value: this.num++, done: false };
}
};
};
const counter = new Counter(3);
for (const number of counter) {
console.log(number); // 0, 1, 2
}Tests if an object implements the Iterator protocol via Symbol.iterator or "@@iterator" method.
/**
* Tests if object implements Iterator protocol
* @param obj - Value to test for Iterable protocol
* @returns true if object is Iterable
*/
function isIterable(obj: any): obj is Iterable<any>;Usage Examples:
import { isIterable } from "iterall";
isIterable([1, 2, 3]); // true - Arrays are iterable
isIterable("ABC"); // true - Strings are iterable
isIterable(new Map()); // true - Maps are iterable
isIterable(new Set()); // true - Sets are iterable
isIterable({ length: 3 }); // false - Array-like but not iterable
isIterable({ key: "value" }); // false - Plain objects are not iterableTests if an object implements the Array-like protocol via defining a positive-integer length property.
/**
* Tests if object implements Array-like protocol
* @param obj - Value to test for Array-like protocol
* @returns true if object is Array-like
*/
function isArrayLike(obj: any): obj is { length: number };Usage Examples:
import { isArrayLike } from "iterall";
isArrayLike([1, 2, 3]); // true - Arrays are array-like
isArrayLike("ABC"); // true - Strings have length
isArrayLike({ length: 1, 0: "A" }); // true - Has numeric length
isArrayLike(new Map()); // false - No length property
isArrayLike({ key: "value" }); // false - No length propertyTests if an object is either Iterable or Array-like. Excludes string literals but includes Arrays and other collection types.
/**
* Tests if object should be iterated over (Iterable or Array-like, excluding strings)
* @param obj - Object value to test
* @returns true if object is a collection that should be iterated
*/
function isCollection(obj: any): obj is Iterable<any> | { length: number };Usage Examples:
import { isCollection, forEach } from "iterall";
isCollection([1, 2, 3]); // true - Arrays
isCollection("ABC"); // false - Strings excluded
isCollection({ length: 1, 0: "A" }); // true - Array-like objects
isCollection(new Map()); // true - Iterable objects
isCollection({ key: "value" }); // false - Plain objects
// Common usage pattern
if (isCollection(obj)) {
forEach(obj, (value) => {
console.log(value);
});
}Returns the Iterator object if the provided object implements the Iterator protocol, otherwise returns undefined.
/**
* Gets Iterator from an Iterable object
* @param iterable - Iterable object to get Iterator from
* @returns Iterator instance or undefined
*/
function getIterator<TValue>(iterable: Iterable<TValue>): Iterator<TValue>;
function getIterator(iterable: any): void | Iterator<any>;Usage Example:
import { getIterator } from "iterall";
const iterator = getIterator([1, 2, 3]);
if (iterator) {
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
}Returns the method responsible for producing the Iterator object. Used for performance tuning in rare cases.
/**
* Gets the @@iterator method from an Iterable object
* @param iterable - Iterable object with @@iterator method
* @returns @@iterator method or undefined
*/
function getIteratorMethod<TValue>(iterable: Iterable<TValue>): () => Iterator<TValue>;
function getIteratorMethod(iterable: any): void | (() => Iterator<any>);Usage Example:
import { getIteratorMethod } from "iterall";
const myArray = [1, 2, 3];
const method = getIteratorMethod(myArray);
if (method) {
const iterator = method.call(myArray);
console.log(iterator.next()); // { value: 1, done: false }
}Creates an Iterator for both Iterable and non-Iterable Array-like collections. Provides universal Iterator creation with fallback support.
/**
* Creates Iterator from Iterable or Array-like collection
* @param collection - Iterable or Array-like object
* @returns Iterator instance or undefined
*/
function createIterator<TValue>(collection: Iterable<TValue>): Iterator<TValue>;
function createIterator(collection: { length: number }): Iterator<any>;
function createIterator(collection: any): void | Iterator<any>;Usage Examples:
import { createIterator } from "iterall";
// Works with Iterables
const iterableIterator = createIterator([1, 2, 3]);
// Works with Array-like objects
const arrayLike = { length: 3, 0: "Alpha", 1: "Bravo", 2: "Charlie" };
const arrayLikeIterator = createIterator(arrayLike);
if (arrayLikeIterator) {
console.log(arrayLikeIterator.next()); // { value: "Alpha", done: false }
console.log(arrayLikeIterator.next()); // { value: "Bravo", done: false }
console.log(arrayLikeIterator.next()); // { value: "Charlie", done: false }
console.log(arrayLikeIterator.next()); // { value: undefined, done: true }
}Iterates over Iterable or Array-like collections, calling a callback at each iteration. Delegates to native forEach when available for optimal performance.
/**
* Iterates over collection, calling callback for each item
* @param collection - Iterable or Array-like object to iterate
* @param callbackFn - Function called for each item (value, index, collection)
* @param thisArg - Optional value to use as 'this' in callback
*/
function forEach<TCollection extends Iterable<any>>(
collection: TCollection,
callbackFn: (value: ValueOf<TCollection>, index: number, collection: TCollection) => any,
thisArg?: any
): void;
function forEach<TCollection extends { length: number }>(
collection: TCollection,
callbackFn: (value: any, index: number, collection: TCollection) => any,
thisArg?: any
): void;Usage Examples:
import { forEach } from "iterall";
// Basic iteration
forEach([1, 2, 3], (value, index) => {
console.log(`Index ${index}: ${value}`);
});
// Works with any collection type
forEach(new Set(["a", "b", "c"]), (value) => {
console.log(value);
});
// Array-like objects
const nodeList = document.querySelectorAll("div");
forEach(nodeList, (element, index) => {
element.textContent = `Div ${index}`;
});
// Using thisArg
const context = { prefix: "Item: " };
forEach([1, 2, 3], function(value) {
console.log(this.prefix + value);
}, context);Error Handling:
The forEach function includes protection against infinite iterators:
// Will throw TypeError after 9,999,999 iterations
// "Near-infinite iteration."Performance Notes:
Array.prototype.forEach when available