この投稿では、以下の2つを説明します。
- TypeScriptで
asyncとジェネレータの両方を使った関数を定義する方法 - その関数を
forで呼び出す方法
asyncとジェネレータの両方を使った関数を定義する
asyncとジェネレータを使った関数は、asyncキーワードをジェネレータ関数function*に冠することで定義できます:
async function* getNumbers() {
await sleep(1000)
yield 1
await sleep(1000)
yield 2
await sleep(1000)
yield 3
}
戻り値の型注釈を与える場合は、AsyncGenerator<T>を使います:
async function* getNumbers(): AsyncGenerator<number>
以上で、asyncなジェネレータが定義できます。最終形態はこんなかんじになります:
async function* getNumbers(): AsyncGenerator<number> {
await sleep(1000)
yield 1
await sleep(1000)
yield 2
await sleep(1000)
yield 3
}
function sleep(milliseconds: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
asyncなジェネレータ関数を呼び出す方法
asyncなジェネレータ関数を呼び出すには、for awaitを使います。
async function main() {
for await (const number of getNumbers()) {
console.log(number)
}
}
トラブルシューティング
Cannot find name 'AsyncGenerator'.
コンパイル時にAsyncGenerator型が見つからないというエラーが出る場合は、コンパイル設定を変更する必要があります。
AsyncGeneratorはES2018で導入されたので、libもしくはtargetを変更します。
生成されるJavaScriptコードがES2018のシンタックスでいい場合は、targetを"ES2018"以上にするだけで解決します:
tsconfig.json
{
"compilerOptions": {
"target": "ES2018"
}
}
生成するJavaScriptコードをES2018未満にする必要がある場合は、libに"es2018.asyncgenerator"を設定することでコンパイルが通るようになります:
tsconfig.json
{
"compilerOptions": {
"target": "ES2017",
"lib": ["es2017", "es2018.asyncgenerator"]
}
}