async/await support in ES6 targets (Node v4+)
TypeScript now supports asynchronous functions for engines that have native support for ES6 generators, e.g. Node v4 and above. Asynchronous functions are prefixed with the async
keyword; await
suspends the execution until an asynchronous function return promise is fulfilled and unwraps the value from the Promise
returned.
Example
In the following example, each input element will be printed out one at a time with a 400ms delay:
ts"use strict";
// printDelayed is a 'Promise<void>'
async function printDelayed(elements: string[]) {
for (const element of elements) {
await delay(400);
console.log(element);
}
}
async function delay(milliseconds: number) {
return new Promise<void>(resolve => {
setTimeout(resolve, milliseconds);
});
}
printDelayed(["Hello", "beautiful", "asynchronous", "world"]).then(() => {
console.log();
console.log("Printed every element!");
});
For more information see Async Functions blog post.
Support for —target ES6 with —module
TypeScript 1.7 adds ES6
to the list of options available for the --module
flag and allows you to specify the module output when targeting ES6
. This provides more flexibility to target exactly the features you want in specific runtimes.
Example
json{
"compilerOptions": {
"module": "amd",
"target": "es6"
}
}
this-typing
It is a common pattern to return the current object (i.e. this
) from a method to create fluent-style APIs. For instance, consider the following BasicCalculator
module:
tsexport default class BasicCalculator {
public constructor(protected value: number = 0) {}
public currentValue(): number {
return this.value;
}
public add(operand: number) {
this.value += operand;
return this;
}
public subtract(operand: number) {
this.value -= operand;
return this;
}
public multiply(operand: number) {
this.value *= operand;
return this;
}
public divide(operand: number) {
this.value /= operand;
return this;
}
}
A user could express 2 * 5 + 1
as
tsimport calc from "./BasicCalculator";
let v = new calc(2)
.multiply(5)
.add(1)
.currentValue();
This often opens up very elegant ways of writing code; however, there was a problem for classes that wanted to extend from BasicCalculator
. Imagine a user wanted to start writing a ScientificCalculator
:
tsimport BasicCalculator from "./BasicCalculator";
export default class ScientificCalculator extends BasicCalculator {
public constructor(value = 0) {
super(value);
}
public square() {
this.value = this.value ** 2;
return this;
}
public sin() {
this.value = Math.sin(this.value);
return this;
}
}
Because TypeScript used to infer the type BasicCalculator
for each method in BasicCalculator
that returned this
, the type system would forget that it had ScientificCalculator
whenever using a BasicCalculator
method.
For instance:
tsimport calc from "./ScientificCalculator";
let v = new calc(0.5)
.square()
.divide(2)
.sin() // Error: 'BasicCalculator' has no 'sin' method.
.currentValue();
This is no longer the case - TypeScript now infers this
to have a special type called this
whenever inside an instance method of a class. The this
type is written as so, and basically means “the type of the left side of the dot in a method call”.
The this
type is also useful with intersection types in describing libraries (e.g. Ember.js) that use mixin-style patterns to describe inheritance:
tsinterface MyType {
extend<T>(other: T): this & T;
}
ES7 exponentiation operator
TypeScript 1.7 supports upcoming ES7/ES2016 exponentiation operators: **
and **=
. The operators will be transformed in the output to ES3/ES5 using Math.pow
.
Example
tsvar x = 2 ** 3;
var y = 10;
y **= 2;
var z = -(4 ** 3);
Will generate the following JavaScript output:
jsvar x = Math.pow(2, 3);
var y = 10;
y = Math.pow(y, 2);
var z = -Math.pow(4, 3);
Improved checking for destructuring object literal
TypeScript 1.7 makes checking of destructuring patterns with an object literal or array literal initializers less rigid and more intuitive.
When an object literal is contextually typed by the implied type of an object binding pattern:
- Properties with default values in the object binding pattern become optional in the object literal.
- Properties in the object binding pattern that have no match in the object literal are required to have a default value in the object binding pattern and are automatically added to the object literal type.
- Properties in the object literal that have no match in the object binding pattern are an error.
When an array literal is contextually typed by the implied type of an array binding pattern:
- Elements in the array binding pattern that have no match in the array literal are required to have a default value in the array binding pattern and are automatically added to the array literal type.
Example
ts// Type of f1 is (arg?: { x?: number, y?: number }) => void
function f1({ x = 0, y = 0 } = {}) {}
// And can be called as:
f1();
f1({});
f1({ x: 1 });
f1({ y: 1 });
f1({ x: 1, y: 1 });
// Type of f2 is (arg?: (x: number, y?: number) => void
function f2({ x, y = 0 } = { x: 0 }) {}
f2();
f2({}); // Error, x not optional
f2({ x: 1 });
f2({ y: 1 }); // Error, x not optional
f2({ x: 1, y: 1 });
Support for decorators when targeting ES3
Decorators are now allowed when targeting ES3. TypeScript 1.7 removes the ES5-specific use of reduceRight
from the __decorate
helper. The changes also inline calls Object.getOwnPropertyDescriptor
and Object.defineProperty
in a backwards-compatible fashion that allows for a to clean up the emit for ES5 and later by removing various repetitive calls to the aforementioned Object
methods.