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-babel
に optional: ['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-sourcemaps
と babel-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 をかませる必要があるみたいです。