Как включить топ-левел await

Всем привет. Изучаю Тайпскрипт. Прочитал про топ-левел await, пытаюсь его включить в node приложении и никак не получается. Никаких толковых материалов в инете нет. Помогите, плиз.

Что я сделал.

  • npm init
  • npm i -D typescript @types/node ts-node
  • потом еще Нодемон поставил.

Typescript - 5.3.3

Пытаюсь использовать await в index.ts.

  • Он мне пишет: "error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', or 'nodenext', and the 'target' option is set to 'es2017' or higher."
  • Меняю в tsconfig target на es2022, module на node16.
  • Он начинает писать "The current file is a CommonJS module and cannot use 'await' at the top level"
  • Пытаюсь вставить в package.json type: module.
  • Начинает писать "Unknown file extension ".ts"

И тут дальше уже заканчиваются идеи. Помогите, пожалуйста, победить эту фигню.

tsconfig.json

  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }

package.json

  "name": "ts-top-await-template",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "scripts": {
    "dev": "nodemon index.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [ ],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^20.11.19",
    "nodemon": "^3.0.3",
    "ts-node": "^10.9.2",
    "typescript": "^5.3.3"
  }

Запускаю npm run dev


Ответы (1 шт):

Автор решения: Andrei Khotko

Похоже, что у вас, как и у меня, стоит Node 20 версии. Нашел ответ на ваш вопрос тут:

Github ts-node issue: ERR_UNKNOWN_FILE_EXTENSION on Node v20.0.0

Краткая выдержка: ts-node сейчас имеет проблемы совместимости с Node 20. Если вы хотите запускать код на Node 20 используя ts-node, то придется выполнять следующую команду, что лишает нас подробного стектрейса ошибки в случае ee возникновения:

node --loader ts-node/esm main.ts

Таким образом, чтобы заработал top-level await, вам нужно проделать следующие шаги:

  1. В tsconfig.json установить следующие опции (остальные оставить прежними):
    "compilerOptions": {
      "target": "es2022",
      "module": "Node16"
    }
    
  2. в package.json установить "type": "module" и изменить скрипт dev на следующий:
    "scripts": {
      "dev": "nodemon --exec \"node --loader ts-node/esm index.ts",
    },
    
  3. Выполните npm run dev.

Для примера, оставлю тут свой тестовый index.ts:

async function waitForCookie(): Promise<string> {
  return new Promise((resolve) => {
    console.log('[INSIDE-FUNC] start cooking a cookie!');

    setTimeout(() => {
      console.log('[INSIDE-FUNC] cookie is ready, take it!!');
      resolve('Chocolate COOKIE!');
    }, 3000);
  })
}

const cookie = await waitForCookie();
console.log('[TOP-LEVEL] Received a cookie:', cookie);

Результат выполнения:

> [email protected] dev
> nodemon --exec "node --loader ts-node/esm index.ts

[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node --loader ts-node/esm index.ts`
(node:26944) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("ts-node/esm", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)
[INSIDE-FUNC] start cooking a cookie!
[INSIDE-FUNC] cookie is ready, take it!!
[TOP-LEVEL] Received a cookie: Chocolate COOKIE!
[nodemon] clean exit - waiting for changes before restart
→ Ссылка