Iterator itself is not a TypeScript or ES6 feature, Iterator is a Behavioral Design Pattern common for Object oriented programming languages. It is, generally, an object which implements the following interface:
Imagine that there's an object of some frame, which includes the list of components of which this frame consists. With Iterator interface it is possible to retrieve components from this frame object like below:
classComponent {constructor (public name:string) {}}classFrameimplementsIterator<Component> {private pointer =0;constructor(public name:string,public components:Component[]) {}publicnext():IteratorResult<Component> {if (this.pointer <this.components.length) {return { done:false, value:this.components[this.pointer++] } } else {return { done:true } } }}let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]);
let iteratorResult1 =frame.next(); //{ done: false, value: Component { name: 'top' } }let iteratorResult2 =frame.next(); //{ done: false, value: Component { name: 'bottom' } }let iteratorResult3 =frame.next(); //{ done: false, value: Component { name: 'left' } }let iteratorResult4 =frame.next(); //{ done: false, value: Component { name: 'right' } }let iteratorResult5 =frame.next(); //{ done: true }//It is possible to access the value of iterator result via the value property:let component =iteratorResult1.value; //Component { name: 'top' }
Again. Iterator itself is not a TypeScript feature, this code could work without implementing Iterator and IteratorResult interfaces explicitly. However, it is very helpful to use these common ES6 interfaces for code consistency.
Ok, Nice, but could be more helpful. ES6 defines the iterable protocol which includes the [Symbol.iterator] symbol if the Iterable interface is implemented:
//...classFrameimplementsIterable<Component> {constructor(public name:string,public components:Component[]) {} [Symbol.iterator]() {let pointer =0;let components =this.components;return {next():IteratorResult<Component> {if (pointer <components.length) {return { done:false, value: components[pointer++] } } else {return { done:true, value:null } } } } }}let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]);
for (let cmp of frame) {console.log(cmp);}
Unfortunately frame.next() won't work with this pattern and it also looks a bit clunky. IterableIterator interface to the rescue!
Code examples above require ES6 target. However, it could work with ES5 target as well if target JS engine supports Symbol.iterator. This can be achieved by using ES6 lib with ES5 target (add es6.d.ts to your project) to make it compile. Compiled code should work in node 4+, Google Chrome and in some other browsers.