iter is just an iterator, not an iterable. The spread operator wants something with Symbol.iterator, and the object returned by range(...)[Symbol.iterator]() only has next().
Fix is either don’t pull the iterator out in the first place:
iter is the iterator object (just next()), not an iterable, so ...iter blows up because there’s no [Symbol.iterator]() on it.
Either spread the iterable you got from range ([...range(1, 4)]), or make the iterator return itself: iter[Symbol.iterator] = function () { return this; } before spreading.
One extra wrinkle: a lot of built-in iterators (like []. values()) are iterable iterators because their Symbol. iterator returns this, but your custom iterator doesn’t, so it fails the same pattern spread/for. . of expects. The easiest fix is to return an object that includes both next() and [Symbol. iterator]() from the start, so you don’t have to patch iter after the fact:
function range(from, to) {
let current = from;
return {
next() {
if (current <= to) return { value: current++, done: false };
return { done: true };
},
[Symbol.iterator]() {
return this;
}
};
}
const iter = range(1, 4);
console.log([...iter]); // [1, 2, 3, 4]
I found a related kirupa. com article that can help you go deeper into this topic: