TypeScript で Generator を ES5 に変換しようとすると Generators are only available when targeting ECMAScript 6 or higher. と怒られます。Babel を組み合わせて ES5 向けに Generator を使ってみます。

gulp で変換

まずは Generator を使ったプログラムを書きます。

// a.ts

function* count() {
    let i = 0;
    for (let i = 0;;) yield i++;
}

const c = count();
console.log(c.next()); // { value: 0, done: false }
console.log(c.next()); // { value: 1, done: false }
console.log(c.next()); // { value: 2, done: false }
console.log(c.next()); // { value: 3, done: false }

0 から 1 ずつ増えるカウンタです。

gulp を使って TypeScript と Babel を組み合わせます。

$ npm install -g gulp
$ npm install -D gulp gulp-babel gulp-typescript
// gulpfile.babel.js

import gulp from 'gulp';
import babel from 'gulp-babel';
import typescript from 'gulp-typescript';

gulp.task('default', () =>
    gulp.src('a.ts')
        .pipe(typescript({
            noEmitOnError: true,
            target: 'es6'
        }))
        .pipe(babel())
        .pipe(gulp.dest('.')));

target: 'es6' を指定してあげます。

gulp コマンドで a.js が出来上がります。が、 node a.js で実行してみるとエラーが出ます。 Babel は Generator の変換に facebook/regenerator を使っているのですが、それのランタイムのコードがないためエラーが出るようです。

babel-node a.js とすれば実行できますが、コードを実行する環境が限られてしまうのが辛いです。

babel-runtime をインストールしたあとに gulp-babeloptional: ['runtime'] というオプションを渡してあげると、 babel-runtime の実装を使う形に変換されました。

$ npm install -S babel-runtime
import gulp from 'gulp';
import babel from 'gulp-babel';
import typescript from 'gulp-typescript';

gulp.task('default', () =>
    gulp.src('a.ts')
        .pipe(typescript({
            noEmitOnError: true,
            target: 'es6'
        }))
        .pipe(babel({
            optional: ['runtime']
        }))
        .pipe(gulp.dest('.')));

mocha で使う場合は -r babel-core/polyfill などとしてもよさそうです。

デバッグとか

わざと count().mext() などと書くと TypeScript に Property 'mext' does not exist on type 'IterableIterator<number>' と怒られます。型のチェックがきちんと働いてくれているのがわかります。

Source Maps を利用するには gulp-sourcemapsbabel-plugin-source-map-support を使います。

npm install -D gulp-sourcemaps babel-plugin-source-map-support source-map-support
import gulp from 'gulp';
import babel from 'gulp-babel';
import sourcemaps from 'gulp-sourcemaps';
import typescript from 'gulp-typescript';

gulp.task('default', () =>
    gulp.src('a.ts')
        .pipe(sourcemaps.init())
        .pipe(typescript({
            noEmitOnError: true,
            target: 'es6'
        }))
        .pipe(babel({
            optional: ['runtime'],
            plugins: ['source-map-support']
        }))
        .pipe(sourcemaps.write())
        .pipe(gulp.dest('.')));

これでエラー位置などが返還前の TypeScript のものになります。

ブラウザとか

Node.js ではなくブラウザで使う場合は更に Browserify をかませる必要があるみたいです。