BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News TypeScript 3.6 Introduces Stricter Generators & Better Promise Handling

TypeScript 3.6 Introduces Stricter Generators & Better Promise Handling

This item in japanese

Bookmarks

The TypeScript team announced the release of TypeScript 3.6, including stricter generators, better developer experience around promises, improvements to array spread accuracy, and a new TypeScript Playground.

Before TypeScript 3.6, it was not possible to differentiate whether values were yielded or returned from generators. TypeScript also would assume the type of yield was any.

With the TypeScript 3.6 release, the type now gets accurately checked for yields, and a new type, Generator, represents generators. The type declarations for Iterator and IteratorResult also get a few new type parameters to support the improvements to type checking for generators in TypeScript. Furthermore, the new Generator type is now also an Iterator and always has both the return and throw methods available.

interface Generator<T = unknown, TReturn = any, TNext = unknown>
        extends Iterator<T, TReturn, TNext> {
    next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
    return(value: TReturn): IteratorResult<T, TReturn>;
    throw(e: any): IteratorResult<T, TReturn>;
    [Symbol.iterator](): Generator<T, TReturn, TNext>;
}

To differentiate between returned and yielded values, the IteratorResult type gets converted to a discriminated union type.

The results of this effort, as explained by TypeScript program manager Daniel Rosenwasser:

TypeScript 3.6 can now narrow down values from iterators when dealing with them directly. To correctly represent the types that can be passed into a generator from calls to next(), TypeScript 3.6 also infers certain uses of yield within the body of a generator function.

TypeScript 3.6 strives to improve developer experience when working with mishandled promises. Common mistakes when working with promises include forgetting to .then() or await the results before passing them to another function. Improvements to TypeScript’s error messages now provide better information to developers. For example:

// Argument of type 'Promise<User>' is not assignable to parameter of type 'User'.
//   ...
// Did you forget to use 'await'?

TypeScript supports targeting various versions of JavaScript. For pre-ES2015 compilation targets, TypeScript typically emits constructs for for/of loops and array spreads, but these can be fairly heavyweight for older versions of JavaScript. TypeScript 3.6 now provides a more straightforward default emit only supporting array types, with support for iterating on other types using the --downlevelIteration flag. With this compilation flag, the transpiled code improves in its accuracy but is much larger.

Instead of using slice() and built-ins, TypeScript 3.6 adds a new __spreadArrays helper to accurately support what happens in ECMAScript 2015 in older targets outside of --downlevelIteration. The __spreadArrays helper is also available in tslib, a runtime library of TypeScript helpers.

Prior to TypeScript 3.6, the language did not allow get and set accessors for ambient contexts. Accessors were treated as being the same as properties. The ECMAScript class fields proposal may introduce differing behavior, and to support this behavior and provide appropriate errors in subclasses, getters and setters in ambient contexts is now supported in TypeScript 3.6.

declare class Foo {
    // Allowed in 3.6+.
    get x(): number;
    set x(val: number): void;
}

TypeScript 3.7 will leverage this improvement and emit get/set accessors for generated .d.ts files.

Before TypeScript 3.6, merging classes and functions would error under any circumstances. With TypeScript 3.6, ambient classes and functions can now merge. This merging change allows a callable constructor pattern to easily get expressed while also allowing namespaces to merge with these declarations. In TypeScript 3.7, the .d.ts files generated from .js files can capture the callability and constructability of class-like functions.

TypeScript 3.0 added the --build flag to support referencing other projects during build time, and TypeScript 3.4 introduced the --incremental flag for saving information from previous compilations to only rebuild certain files. Before TypeScript 3.6, these flags did not work with third-party build tools such as Webpack. TypeScript 3.6 now provides two sets of APIs to operate on project references and incremental program building. As detailed by Rosenwasser:

For creating --incremental builds, users can leverage the createIncrementalProgram and createIncrementalCompilerHost APIs. Users can also re-hydrate old program instances from .tsbuildinfo files generated by this API using the newly exposed readBuilderProgram function, which is only meant to be used as for creating new programs (i.e., you can’t modify the returned instance – it’s only meant to be used for the oldProgram parameter in other create*Program functions). For leveraging project references, a new createSolutionBuilder function has been exposed, which returns an instance of the new type SolutionBuilder.

The TypeScript Playground receives a substantial refresh thanks to Artem Tyurin, adding a significant number of improvements to the playground, making it easier to experiment with TypeScript.

Other TypeScript 3.6 improvements include:

  • Support for Unicode characters in identifiers when emitting to ES2015 and later targets
  • import.meta Support in SystemJS
  • Semicolon-Aware Code Edits
  • Smarter Auto-Imports

TypeScript 3.6 introduces potentially breaking changes, all of which are consequences of using the new features or changes emerging in the ECMAScript standard:

  • Class Members Named "constructor" Are Now Constructors
  • The global window is no longer defined as type Window, but now as type Window & typeof globalThis
  • GlobalFetch gets replaced with WindowOrWorkerGlobalScope
  • Some non-standard properties on Navigator get removed
  • The experimental-webgl context gets replaced with webgl and webgl2
  • JSDoc Comments No Longer Merge
  • Keywords Cannot Contain Escape Sequences

The TypeScript team is already working on features for TypeScript 3.7, including leveraging features introduced in TypeScript 3.6 with generated type definitions.

The TypeScript community is also preparing for the second TSConf event on October 11th with TypeScript founder Anders Hejlsberg delivering the keynote.

TypeScript is open source software available under the Apache 2 license. Contributions and feedback are encouraged via the TypeScript GitHub project and should follow the TypeScript contribution guidelines and Microsoft open source code of conduct.

Rate this Article

Adoption
Style

BT