async functionの中でしか使えなかったawaitがモジュールのTop Levelで使えるようになった。モジュールの中で以下のような書き方ができる。 ```ts async function lazyInit() { // 中略 } await lazyInit(); // 中略 export {}; ``` ただしいくつか制約がある。 - [[Top-Level await]]を使うコードで `import`または`export`の記述が必要 - [[TypeScript]]がそれをもってファイルをmoduleであると判断するため - [[target (tsconfig)|target]]が`es2017`以上でなければいけない - [[module (tsconfig)|module]]が`esnext`または`system`でなければいけない ## 具体例 指定ミリ秒スリープさせる`asyncSleep`を呼ぶコードについて、[[Top-Level await]]の有無で`main.ts`がどのように変わるか比較してみる。 ```ts console.log("Load module.ts"); export const asyncSleep = (ms: number) => new Promise((resolve) => { console.log("Begin sleep"); setTimeout(() => { console.log("End sleep"); resolve(); }, ms); }); ``` ### [[Top-Level await]]なし `tsconfig.json` ```json { "compilerOptions": { "target": "es2020", "module": "CommonJS", // 中略 } } ``` `main.ts` ```ts import { asyncSleep } from "./module.js"; console.log("Call asyncSleep begin"); await asyncSleep(3000); console.log("Call asyncSleep end"); ``` 実行結果は以下のとおり。 ```bash Load module.ts Call asyncSleep begin Begin sleep Call asyncSleep end # 3秒待つ End sleep Finish ``` ### [[Top-Level await]]あり `tsconfig.json` ```json { "compilerOptions": { "target": "es2020", "module": "esnext", // 中略 } } ``` [[Node.jsがファイルをES modulesと認識する条件]]を満たすため、`package.json`と`main.ts`のimportを若干変更している。 `package.json` ```json { // 中略 "type": "module" } ``` `main.ts` ```ts // .js拡張子を追加 import { asyncSleep } from "./module.js"; console.log("Call asyncSleep begin"); await asyncSleep(3000); console.log("Call asyncSleep end"); ``` 実行結果は以下のとおり。 ```bash Load module.ts Call asyncSleep begin Begin sleep # 3秒待つ End sleep Call asyncSleep end ```