# TypeScript 1.7

# 支持 async / await 编译到 ES6 (Node v4+)

TypeScript 目前在已经原生支持 ES6 generator 的引擎 (比如 Node v4 及以上版本) 上支持异步函数。异步函数前置 async 关键字; await 会暂停执行,直到一个异步函数执行后返回的 promise 被 fulfill 后获得它的值.

# 例子

在下面的例子中,输入的内容将会延时 400 毫秒逐个打印:

'use strict';

// printDelayed 返回值是一个 '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('打印每一个内容!');
});

查看 Async Functions (opens new window) 一文了解更多.

# 支持同时使用 --target ES6--module

TypeScript 1.7 将 ES6 添加到了 --module 选项支持的选项的列表,当编译到 ES6 时允许指定模块类型。这让使用具体运行时中你需要的特性更加灵活.

# 例子

{
    "compilerOptions": {
        "module": "amd",
        "target": "es6"
    }
}

# this 类型

在方法中返回当前对象 (也就是 this ) 是一种创建链式 API 的常见方式。比如,考虑下面的 BasicCalculator 模块:

export 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;
  }
}

使用者可以这样表述 2 * 5 + 1 :

import calc from './BasicCalculator';

let v = new calc(2).multiply(5).add(1).currentValue();

这使得这么一种优雅的编码方式成为可能;然而,对于想要去继承 BasicCalculator 的类来说有一个问题。想象使用者可能需要编写一个 ScientificCalculator :

import 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;
  }
}

因为 BasicCalculator 的方法返回了 this , TypeScript 过去推断的类型是 BasicCalculator , 如果在 ScientificCalculator 的实例上调用属于 BasicCalculator 的方法,类型系统不能很好地处理.

举例来说:

import calc from './ScientificCalculator';

let v = new calc(0.5)
  .square()
  .divide(2)
  .sin() // Error: 'BasicCalculator' 没有 'sin' 方法.
  .currentValue();

这已经不再是问题 - TypeScript 现在在类的实例方法中,会将 this 推断为一个特殊的叫做 this 的类型. this 类型也就写作 this , 可以大致理解为 "方法调用时点左边的类型".

this 类型在描述一些使用了 mixin 风格继承的库 (比如 Ember.js) 的交叉类型:

interface MyType {
  extend<T>(other: T): this & T;
}

# ES7 幂运算符

TypeScript 1.7 支持将在 ES7/ES2016 中增加的幂运算符 (opens new window): ****= . 这些运算符会被转换为 ES3/ES5 中的 Math.pow .

# 举例

var x = 2 ** 3;
var y = 10;
y **= 2;
var z = -(4 ** 3);

会生成下面的 JavaScript:

var x = Math.pow(2, 3);
var y = 10;
y = Math.pow(y, 2);
var z = -Math.pow(4, 3);

# 改进对象字面量解构的检查

TypeScript 1.7 使对象和数组字面量解构初始值的检查更加直观和自然.

当一个对象字面量通过与之对应的对象解构绑定推断类型时:

  • 对象解构绑定中有默认值的属性对于对象字面量来说可选.
  • 对象解构绑定中的属性如果在对象字面量中没有匹配的值,则该属性必须有默认值,并且会被添加到对象字面量的类型中.
  • 对象字面量中的属性必须在对象解构绑定中存在.

当一个数组字面量通过与之对应的数组解构绑定推断类型时:

  • 数组解构绑定中的元素如果在数组字面量中没有匹配的值,则该元素必须有默认值,并且会被添加到数组字面量的类型中.

# 举例

// f1 的类型为 (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 });

// f2 的类型为 (arg?: (x: number, y?: number) => void
function f2({ x, y = 0 } = { x: 0 }) {}

f2();
f2({}); // 错误, x 非可选
f2({ x: 1 });
f2({ y: 1 }); // 错误, x 非可选
f2({ x: 1, y: 1 });

# 装饰器 (decorators) 支持的编译目标版本增加 ES3

装饰器现在可以编译到 ES3. TypeScript 1.7 在 __decorate 函数中移除了 ES5 中增加的 reduceRight . 相关改动也内联了对 Object.getOwnPropertyDescriptorObject.defineProperty 的调用,并向后兼容,使 ES5 的输出可以消除前面提到的 Object 方法的重复 [1].