patterntypescriptTip
Iterator Pattern: Traverse Collections Without Exposing Internal Structure
Viewed 0 times
iterator patternbehavioral patternSymbol.iteratoriterablegeneratorfor ofcustom collection
Problem
Client code that traverses a collection is tied to its internal representation (array index, linked list pointer, tree traversal order). Changing the collection structure breaks traversal code.
Solution
Implement the JavaScript iterator protocol (
Symbol.iterator + next()) so the collection works with for...of, spread, and destructuring.class Range {
constructor(private start: number, private end: number, private step = 1) {}
[Symbol.iterator](): Iterator<number> {
let current = this.start;
const end = this.end;
const step = this.step;
return {
next(): IteratorResult<number> {
if (current < end) {
const value = current;
current += step;
return { value, done: false };
}
return { value: undefined as never, done: true };
},
};
}
}
const range = new Range(0, 10, 2);
for (const n of range) console.log(n); // 0 2 4 6 8
const arr = [...range]; // [0, 2, 4, 6, 8]Why
Following the native iterator protocol means the custom collection works with all built-in iteration consumers (
for...of, spread, Array.from, destructuring) without any adaptation.Gotchas
- The iterator is stateful — it cannot be reset unless you implement
return()and track position carefully. Create a new iterator for each traversal. - Generator functions (
function*) are the idiomatic TypeScript way to implement iterators and handle the protocol boilerplate automatically. - Iterators are lazy by nature — they compute values on demand, which is efficient for large or infinite sequences.
Revisions (0)
No revisions yet.