Generators and Iteration for ES5/ES3

First some ES2016 terminology:

Iterators

ES2015 introduced Iterator, which is an object that exposes three methods, next, return, and throw, as per the following interface:

  1. interface Iterator<T> {
  2. next(value?: any): IteratorResult<T>;
  3. return?(value?: any): IteratorResult<T>;
  4. throw?(e?: any): IteratorResult<T>;
  5. }

This kind of iterator is useful for iterating over synchronously available values, such as the elements of an Array or the keys of a Map.An object that supports iteration is said to be “iterable” if it has a Symbol.iterator method that returns an Iterator object.

The Iterator protocol also defines the target of some of the ES2015 features like for..of and spread operator and the array rest in destructuring assignmnets.

Generators

ES2015 also introduced “Generators”, which are functions that can be used to yield partial computation results via the Iterator interface and the yield keyword.Generators can also internally delegate calls to another iterable through yield *. For example:

  1. function* f() {
  2. yield 1;
  3. yield* [2, 3];
  4. }

New —downlevelIteration

Previously generators were only supported if the target is ES6/ES2015 or later.Moreover, constructs that operate on the Iterator protocol, e.g. for..of were only supported if they operate on arrays for targets below ES6/ES2015.

TypeScript 2.3 adds full support for generators and the Iterator protocol for ES3 and ES5 targets with —downlevelIteration flag.

With —downlevelIteration, the compiler uses new type check and emit behavior that attempts to call a Symbol.iterator method on the iterated object if it is found, and creates a synthetic array iterator over the object if it is not.

Please note that this requires a native Symbol.iterator or Symbol.iterator shim at runtime for any non-array values.

for..of statements, Array Destructuring, and Spread elements in Array, Call, and New expressions support Symbol.iterator in ES5/E3 if available when using —downlevelIteration, but can be used on an Array even if it does not define Symbol.iterator at run time or design time.