Was this page helpful?

TypeScript 2.3

Generators and Iteration for ES5/ES3

First some ES2016 terminology:

Iterators

ES2015 introducedIterator, which is an object that exposes three methods,next,return, andthrow, as per the following interface:

ts
interfaceIterator<T> {
next(value?:any):IteratorResult<T>;
return?(value?:any):IteratorResult<T>;
throw?(e?:any):IteratorResult<T>;
}

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 aSymbol.iterator method that returns anIterator object.

The Iterator protocol also defines the target of some of the ES2015 features likefor..of and spread operator and the array rest in destructuring assignments.

Generators

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

ts
function*f() {
yield1;
yield* [2,3];
}
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 withdownlevelIteration flag.

WithdownlevelIteration, 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 nativeSymbol.iterator orSymbol.iterator shim at runtime for any non-array values.

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

Async Iteration

TypeScript 2.3 adds support for the async iterators and generators as described by the currentTC39 proposal.

Async iterators

The Async Iteration introduces anAsyncIterator, which is similar toIterator.The difference lies in the fact that thenext,return, andthrow methods of anAsyncIterator return aPromise for the iteration result, rather than the result itself.This allows the caller to enlist in an asynchronous notification for the time at which theAsyncIterator has advanced to the point of yielding a value.AnAsyncIterator has the following shape:

ts
interfaceAsyncIterator<T> {
next(value?:any):Promise<IteratorResult<T>>;
return?(value?:any):Promise<IteratorResult<T>>;
throw?(e?:any):Promise<IteratorResult<T>>;
}

An object that supports async iteration is said to be “iterable” if it has aSymbol.asyncIterator method that returns anAsyncIterator object.

Async Generators

TheAsync Iteration proposal introduces “Async Generators”, which are async functions that also can be used to yield partial computation results.Async Generators can also delegate calls viayield* to either an iterable or async iterable:

ts
asyncfunction*g() {
yield1;
awaitsleep(100);
yield* [2,3];
yield* (asyncfunction*() {
awaitsleep(100);
yield4;
})();
}

As with Generators, Async Generators can only be function declarations, function expressions, or methods of classes or object literals.Arrow functions cannot be Async Generators. Async Generators require a valid, globalPromise implementation (either native or an ES2015-compatible polyfill), in addition to a validSymbol.asyncIterator reference (either a native symbol or a shim).

Thefor-await-of Statement

Finally, ES2015 introduced thefor..of statement as a means of iterating over an iterable.Similarly, the Async Iteration proposal introduces thefor..await..of statement to iterate over an async iterable:

ts
asyncfunctionf() {
forawait (constxofg()) {
console.log(x);
}
}

Thefor..await..of statement is only legal within an Async Function or Async Generator.

Caveats
  • Keep in mind that our support for async iterators relies on support forSymbol.asyncIterator to exist at runtime. You may need to polyfillSymbol.asyncIterator, which for simple purposes can be as simple as:(Symbol as any).asyncIterator = Symbol.asyncIterator || Symbol.for("Symbol.asyncIterator");
  • You also need to includeesnext in yourlib option, to get theAsyncIterator declaration if you do not already have it.
  • Finally, if your target is ES5 or ES3, you’ll also need to set the--downlevelIterators flag.

Generic parameter defaults

TypeScript 2.3 adds support for declaring defaults for generic type parameters.

Example

Consider a function that creates a newHTMLElement, calling it with no arguments generates aDiv; you can optionally pass a list of children as well. Previously you would have to define it as:

ts
declarefunctioncreate():Container<HTMLDivElement,HTMLDivElement[]>;
declarefunctioncreate<TextendsHTMLElement>(element:T):Container<T,T[]>;
declarefunctioncreate<TextendsHTMLElement,UextendsHTMLElement>(
element:T,
children:U[]
):Container<T,U[]>;

With generic parameter defaults we can reduce it to:

ts
declarefunctioncreate<TextendsHTMLElement =HTMLDivElement,U =T[]>(
element?:T,
children?:U
):Container<T,U>;

A generic parameter default follows the following rules:

  • A type parameter is deemed optional if it has a default.
  • Required type parameters must not follow optional type parameters.
  • Default types for a type parameter must satisfy the constraint for the type parameter, if it exists.
  • When specifying type arguments, you are only required to specify type arguments for the required type parameters. Unspecified type parameters will resolve to their default types.
  • If a default type is specified and inference cannot choose a candidate, the default type is inferred.
  • A class or interface declaration that merges with an existing class or interface declaration may introduce a default for an existing type parameter.
  • A class or interface declaration that merges with an existing class or interface declaration may introduce a new type parameter as long as it specifies a default.

New--strict master option

New checks added to TypeScript are often off by default to avoid breaking existing projects.While avoiding breakage is a good thing, this strategy has the drawback of making it increasingly complex to choose the highest level of type safety, and doing so requires explicit opt-in action on every TypeScript release.With thestrict option it becomes possible to choose maximum type safety with the understanding that additional errors might be reported by newer versions of the compiler as improved type checking features are added.

The newstrict compiler option represents the recommended setting of a number of type checking options. Specifically, specifyingstrict corresponds to specifying all of the following options (and may in the future include more options):

In exact terms, thestrict option sets thedefault value for the compiler options listed above.This means it is still possible to individually control the options.For example,

sh
--strict --noImplicitThisfalse

has the effect of turning on all strict optionsexcept thenoImplicitThis option. Using this scheme it is possible to express configurations consisting ofall strict options except some explicitly listed options.In other words, it is now possible to default to the highest level of type safety but opt out of certain checks.

Starting with TypeScript 2.3, the defaulttsconfig.json generated bytsc --init includes a"strict": true setting in the"compilerOptions" section.Thus, new projects started withtsc --init will by default have the highest level of type safety enabled.

Enhanced--init output

Along with settingstrict on by default,tsc --init has an enhanced output. Defaulttsconfig.json files generated bytsc --init now include a set of the common compiler options along with their descriptions commented out.Just un-comment the configuration you like to set to get the desired behavior; we hope the new output simplifies the setting up new projects and keeps configuration files readable as projects grow.

Errors in .js files with--checkJs

By default the TypeScript compiler does not report any errors in .js files including usingallowJs.With TypeScript 2.3 type-checking errors can also be reported in.js files withcheckJs.

You can skip checking some files by adding// @ts-nocheck comment to them; conversely you can choose to check only a few.js files by adding// @ts-check comment to them without settingcheckJs.You can also ignore errors on specific lines by adding// @ts-ignore on the preceding line.

.js files are still checked to ensure that they only include standard ECMAScript features; type annotations are only allowed in.ts files and are flagged as errors in.js files.JSDoc comments can be used to add some type information to your JavaScript code, seeJSDoc Support documentation for more details about the supported JSDoc constructs.

SeeType checking JavaScript Files documentation for more details.

The TypeScript docs are an open source project. Help us improve these pagesby sending a Pull Request

Contributors to this page:
MHMohamed Hegazy  (51)
OTOrta Therox  (12)
NSNick Schonning  (1)
JBJack Bates  (1)
LRLars Reimann  (1)
7+

Last updated: Jul 14, 2025