TypeScript 1.7

ES6(Node v4+)対象時のasync/awaitサポート

TypeScriptはES6のジェネレーターをネイティブでサポートするエンジンを持つもの(例: Node v4以上)に対して、 非同期関数をサポートするようになりました。 非同期関数には、接頭辞としてasyncキーワードが付きます。 awaitは非同期関数がPromiseを解決し、そこから返される値が明らかになるまで実行を中断します。

次の例では、各入力要素が200ms遅延して1つずつ出力されます。

"use strict";

// printDelayed is a 'Promise<void>'
async function printDelayed(elements: string[]) {
    for (const element of elements) {
        await delay(200);
        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!");
});

詳細については、Async Functionsのブログ投稿を参照してください。

--moduleを使用した--target ES6のサポート

TypeScript 1.7では--moduleフラグで利用可能なオプションの一覧にES6が追加され、 ES6を対象とした際にモジュールの出力が指定できるようになりました。 これにより、特定のランタイムで必要な機能を正確に対象とする場合の柔軟性が向上します。

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

thisの型付け

これは、現在のオブジェクト(例えば、this)をメソッドから返す、 fluent-style(メソッドチェーン)の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;
    }
}

TypeScriptはBasicCalculatorの各メソッドが返すthisBasicCalculator型と推測するので、 BasicCalculatorのメソッドが使われる度に、型システムはScientificCalculatorを持っていたことを忘れてしまいます。

下記はその一例になります。

import calc from "./ScientificCalculator";

let v = new calc(0.5)
    .square()
    .divide(2)
    .sin()    // Error: 'BasicCalculator' has no 'sin' method.
    .currentValue();

ただし、今後はこのような現象は起こらなくなります。 TypeScriptはクラスのインスタンスメソッド内部にいる限り、thisに対してthisという特別な型を持つと推測するようになります。 this型はこのように記述され、基本的には「メソッド呼び出しにおけるドットの左側の型」を意味します。

このthis型は継承を表すためのmixinパターンを使用するdescribingライブラリ(例えばEmber.js)の交差型でも有用です。

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

ES7のexponentiation(べき乗)演算子

TypeScript 1.7は、ES7/ES2016 exponentiation operators****=をサポートします。 演算子は、Math.powを使用してES3/ES5に変換されます。

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では、オブジェクトリテラルまたは配列リテラル初期化の分割パターンのチェックが多少緩くなり、より直感的になりました。

オブジェクトリテラルが暗黙の型のオブジェクト・バインディング・パターンによって文脈的に型付けされるとき、

  • オブジェクト・バインディング・パターンのデフォルト値を持つプロパティは、オブジェクトリテラルでは任意になります。
  • オブジェクトリテラルに一致するものがないオブジェクト・バインディング・パターンのプロパティは、 オブジェクト・バインディング・パターンにデフォルト値を持つ必要があり、自動的にオブジェクトリテラル型に追加されます。
  • オブジェクト・バインディング・パターンに一致しないオブジェクトリテラルのプロパティはエラーです。

配列リテラルが配列バインディング・パターンの暗黙の型によって文脈上の型付けされているとき、

  • 配列リテラルに一致しない配列バインディング・パターンの要素は、配列バインディング・パターンにデフォルト値を持つ必要があり、 自動的に配列リテラル型に追加されます。
// 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 });

ES3対象時のデコレータのサポート

デコレータがES3を対象とした際にも使用できるようになりました。 TypeScript 1.7では、__decorateヘルパーからES5固有のreduceRightの使用を取り除きました。

この変更はインラインでObject.getOwnPropertyDescriptorObject.definePropertyを後方互換性のある方法で呼び出すため、 上記のObjectメソッドに対するさまざまな繰り返し呼び出しを削除するため、ES5以降の出力のクリーンアップにもなります。

 Back to top

© https://github.com/Microsoft/TypeScript-Handbook

このページは、ページトップのリンク先のTypeScript-Handbook内のページを翻訳した内容を基に構成されています。 下記の項目を確認し、必要に応じて公式のドキュメントをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • ドキュメントの情報が古い可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報やより分かり易くするための追記を行っている事があります。