Iterator Pattern in TypeScript — ✨ Structural Design Pattern #3

365kim
2 min readJul 30, 2023

--

Photo by Nicolene Olckers on Unsplash

🙋🏻‍♀️ What is the Iterator Pattern?

The Iterator Pattern is a behavioral design pattern that provides a way to access the elements of an aggregate object (such as an array or a list) sequentially without exposing its underlying representation. This pattern abstracts the details related to accessing and traversing the elements of the aggregate object, making it easy to work with complex data structures.

  • Iterator: an interface that defines the methods required to traverse a collection (like next(), hasNext()).
  • Aggregate: an interface representing a collection of objects, which returns an instance of the Concrete Iterator.

✨ Simple TypeScript Example

Let’s start with the Iterator interface. The Iterator interface mandates the next() and hasNext() methods.

interface Iterator<T> {
next(): T
hasNext(): boolean
}

The Aggregate interface provides a method to get an Iterator object.

interface Aggregate<T> {
createIterator(): Iterator<T>
}

Here’s a Concrete Iterator for an array.

class ArrayIterator<T> implements Iterator<T> {
private collection: T[]
private position: number = 0

constructor(collection: T[]) {
this.collection = collection
}

next(): T {
return this.collection[this.position++]
}

hasNext(): boolean {
return this.position < this.collection.length
}
}

And here’s a Concrete Aggregate, an array that creates ArrayIterators.

class ArrayAggregate<T> implements Aggregate<T> {
private collection: T[]

constructor(collection: T[]) {
this.collection = collection
}

createIterator(): Iterator<T> {
return new ArrayIterator(this.collection)
}
}

In the client code, you create an ArrayAggregate and use an Iterator to traverse it.

const arrayAggregate = new ArrayAggregate([1, 2, 3, 4, 5])
const iterator = arrayAggregate.createIterator()

while (iterator.hasNext()) {
console.log(iterator.next())
}

🧑‍💻 Use it or Avoid it

When to use it:

  • If you want to access elements in complex data structures and don’t want to know the details of how to traverse the structure.
  • If you want to support multiple traversal algorithms with different iterators and choose which to use at runtime.

When to avoid it:

  • For simple structures (like JavaScript arrays), native loops or the forEach method are more straightforward.
  • If you don’t need to support multiple traversal methods, or you’re not trying to encapsulate the traversal operation, an Iterator may be overkill.

--

--

365kim

Web Front-End Developer who believes Every Day Counts!