Back to JavaScript
2026-01-276 min read

TypeError: Iterator/AsyncIterator constructor can't be used directly (JavaScript)

Learn TypeError: Iterator/AsyncIterator constructor can't be used directly (JavaScript) step by step with clear examples and exercises.

Why This Matters

Understanding why you encounter a TypeError: Iterator/AsyncIterator constructor can't be used directly error is crucial for debugging complex JavaScript code, especially when working with iterable objects or asynchronous functions. This error typically occurs when you attempt to use the Iterator or AsyncIterator constructors directly, which are abstract classes and should only be inherited from.

By learning about these errors and how to handle them, you will be better equipped to manage complex data structures and asynchronous operations in your JavaScript projects. Furthermore, mastering iterators and async iterators can help you write more efficient and maintainable code by allowing for easier manipulation of collections and handling of asynchronous tasks.

Prerequisites

Before diving into the core concept, ensure you have a good understanding of:

  1. JavaScript basics, including variables, functions, and data structures like arrays and objects.
  2. ES6 features such as arrow functions, template literals, and destructuring assignments.
  3. Promises and async/await for handling asynchronous operations.
  4. Iterable objects and the for...of loop for iterating over collections.
  5. Understanding of classes and inheritance in JavaScript.
  6. Familiarity with error handling concepts, such as try-catch blocks.
  7. Basic understanding of generators and their use in creating iterables.

Core Concept

The Iterator and AsyncIterator constructors are abstract classes that provide a standard way to traverse collections (like arrays or generators) and asynchronous iterables (like Promises), respectively. These constructors cannot be instantiated directly but should be implemented in custom objects that want to support iteration or asynchronous iteration.

Iterator

An Iterator is an object that allows you to traverse the elements of a collection, one at a time. To create an iterable object, you need to implement the Symbol.iterator method on your custom object. This method should return an object with an [Symbol.iterator]() method that returns the Iterator for the given iterable.

Here's an example of creating a simple iterable object using a generator function:

function* myIterable(start, end) {
let current = start;

while (current <= end) {
yield current++;
}
}

let myIterator = myIterable(1, 5);
let nextResult = myIterator.next();

while (!nextResult.done) {
console.log(nextResult.value); // Outputs: 1, 2, 3, 4, 5
nextResult = myIterator.next();
}

AsyncIterator

An AsyncIterator is similar to an Iterator but for asynchronous operations. To create an asynchronous iterable object, you need to implement the async next() method on your custom object and return a Promise that resolves with an object containing value and done properties.

Here's an example of creating a simple async iterable object using Promises:

let myAsyncIterable = {
[Symbol.asyncIterator]() {
let data = [1, 2, 3];
let index = 0;

return {
next() {
if (index < data.length) {
return Promise.resolve({ value: data[index++], done: false });
} else {
return Promise.resolve({ done: true });
}
}
};
}
};

let asyncIterator = myAsyncIterable[Symbol.asyncIterator]();

(async () => {
let nextResult = await asyncIterator.next();

while (!nextResult.done) {
console.log(nextResult.value); // Outputs: 1, 2, 3
nextResult = await asyncIterator.next();
}
})();

Worked Example

Let's consider a scenario where you want to create an iterable object that yields the Fibonacci sequence using a generator function.

function* fibonacci() {
let [a, b] = [0, 1];

while (true) {
yield a;
[a, b] = [b, a + b];
}
}

let fibIterator = fibonacci();
let nextResult = fibIterator.next();

for (let i = 0; i < 10; i++) {
console.log(nextResult.value); // Outputs: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
nextResult = fibIterator.next();
}

Common Mistakes

  1. Trying to instantiate Iterator or AsyncIterator constructors directly: Remember that these constructors are abstract classes and cannot be instantiated. Instead, create iterable objects by implementing the Symbol.iterator method for regular iterables or the async next() method for async iterables.
  1. Forgetting to return the Iterator or AsyncIterator object from Symbol.iterator: Make sure that your custom object returns an object with an [Symbol.iterator]() method when implementing an iterable.
  1. Not properly handling the done property: In both regular and async iterators, make sure to set the done property to true when there are no more elements to yield.
  1. Incorrect implementation of Symbol.iterator or async next() methods: Ensure that your custom object returns the correct structure for Iterator or AsyncIterator objects and handles edge cases appropriately.
  1. Not using a generator function or Promises in async iterables: When implementing an async iterable, make sure to use a generator function or Promises to handle asynchronous operations correctly.
  1. Ignoring errors during iteration: If an error occurs during the iteration process (either synchronously or asynchronously), it may not be caught and handled properly. Use try-catch blocks within your next() method to ensure that any errors are handled gracefully.

Practice Questions

  1. Create an iterable object that yields the first 20 Fibonacci numbers using a for loop inside the Symbol.iterator method.
  2. Implement an async iterable object that yields the prime numbers between 1 and 50 using Promises in the async next() method.
  3. Given the following code, what is the expected output, and why does it throw a TypeError?
let myIterable = {
[Symbol.iterator]() {
return {
next() {
return { value: 1, done: false };
}
};
}
};

for (let item of new Iterator(myIterable)) {
console.log(item); // Output?
}
  1. Write a function that takes an iterable object and returns a new iterable object that yields the squares of each number in the original iterable. Use a generator function for this task.

FAQ

Why can't I instantiate the Iterator or AsyncIterator constructor directly?

The Iterator and AsyncIterator constructors are abstract classes that should only be inherited from. They provide a standard way to traverse collections and asynchronous iterables, but you should create your own iterable objects by implementing the appropriate methods on custom objects.

How do I know if an object is iterable?

You can check if an object is iterable by attempting to call the Symbol.iterator method on it or using the typeof operator with the Symbol.iterator symbol. If the result is either a function or an object with an [Symbol.iterator]() method, then the object is iterable.

What happens when I use a non-iterable object in a for...of loop?

If you attempt to use a non-iterable object in a for...of loop, JavaScript will throw a TypeError: Iterator or AsyncIterator object is not a function error. To avoid this, make sure your objects implement the necessary methods to be iterable (Symbol.iterator for regular iterables and async next() for async iterables).

What's the purpose of the done property in an Iterator?

The done property in an Iterator indicates whether there are more elements to yield or if the iteration has ended. When the done property is set to true, it signals that there are no more elements left to iterate over. This property helps the loop terminate properly and avoid infinite loops.

How do I create a custom iterable object using a class?

To create a custom iterable object using a class, you can define the [Symbol.iterator]() method on the class prototype and return an object with an async next() or next() method, depending on whether it's an async iterable or not. Here's an example:

class MyIterable {
constructor(data) {
this.data = data;
}

[Symbol.iterator]() {
let index = 0;

return {
next() {
if (index < this.data.length) {
return { value: this.data[index++], done: false };
} else {
return { done: true };
}
}
};
}
}

let myIterable = new MyIterable([1, 2, 3]);
for (let item of myIterable) {
console.log(item); // Outputs: 1, 2, 3
}
TypeError: Iterator/AsyncIterator constructor can't be used directly (JavaScript) | JavaScript | XQA Learn