iterators
Iterators provide a uniform way to step through collections (arrays, maps, sets, strings) one element at a time. In AssemblyScript they are similar as TypeScript: an object exposes a next() method that returns IteratorResult<T>, and an iterable exposes [Symbol.iterator]() that produces such an iterator.
There are 3 kinds of object.
- The upper layer is
Iterableinterface. It should provide[Symbol.iterator]method to return an iterator.tsexport interface Iterable<T> { [Symbol.iterator](): Iterator<T>; } - The middle layer is
Iteratorinterface. It should providenextmethod to return an iterator result.tsexport interface Iterator<T> { next(): IteratorResult<T>; } - The lower layer is
IteratorResult<T>class. It provides 2 readonly fields,doneandvalue.done: boolean flag.falsemeans the iterator can still yield more items;truemarks iteration is finished. Once done is true, consumers (e.g., for...of) stop pulling values.value: payload for the current step. Whendoneisfalse, it holds the next item. When done is true, it’s undefined.
tsAdditional, AS provide 2 helper static functions to define custom iterator.declare class IteratorResult<T> { private constructor(value: T); get done(): boolean; get value(): T; static done<T>(): IteratorResult<T>; static fromValue<T>(value: T): IteratorResult<T>; }IteratorResult.done<T>()to create a finishedIteratorResultwithout any value.IteratorResult.fromValue<T>(value)to create a unfinishedIteratorResultwith value.
Minimal custom iterable
Implement [Symbol.iterator]() to make your type usable with for...of and spread:
ts
class MyIterator implements Iterator<string> {
private index: i32 = 0;
constructor(private items: string[]) {}
next(): IteratorResult<string> {
if (this.index < this.items.length) {
return IteratorResult.fromValue<string>(this.items[this.index++]);
} else {
return IteratorResult.done<string>();
}
}
}
class MyIterable implements Iterable<string> {
private items: string[] = ["a", "b", "c"];
[Symbol.iterator](): MyIterator {
return new MyIterator(this.items);
}
}
export function _start(): void {
const myIterable = new MyIterable();
for (const value of myIterable) {
trace(`value = ${value}`);
// trace: value = a
// trace: value = b
// trace: value = c
}
}Tips
- Keep iterators side-effect free and lazy: compute values only when
next()is called.
With these building blocks you can make your domain objects feel native to TypeScript’s iteration syntax, enabling clean, composable loops and transformations.