38

I was trying to use the top level in the project and saw that it was necessary to change the module from tscofnig to esnext or system, but for some reason my ts-node's error. And I already put the type: module I tried to use the flag: --experimental-modules but the error still does not know how to solve.

package.json:

{
  "name": "micro-hr",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "type": "module",
  "scripts": {
    "commit": "git-cz",
    "build": "babel src --extensions \".js,.ts\" --out-dir dist --copy-files --no-copy-ignored",
    "start:dev": "ts-node-dev --experimental-modules --inspect --respawn --transpile-only --ignore-watch node_modules -r tsconfig-paths/register src/index.ts",
    "start:debug": "node start --debug --watch",
    "start:prod": "node dist/index.ts",
    "test": "jest",
    "lint": "eslint --fix",
    "lint2": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ./ormconfig.ts",
    "migration:generate": "ts-node ./node_modules/typeorm/cli.js migration:generate -n"
  },
  "devDependencies": {
    "@babel/cli": "^7.11.5",
    "@babel/core": "^7.11.5",
    "@babel/node": "^7.10.5",
    "@babel/preset-env": "^7.11.5",
    "@babel/preset-typescript": "^7.10.4",
    "@commitlint/cli": "^9.1.2",
    "@commitlint/config-conventional": "^9.1.2",
    "@types/bcryptjs": "^2.4.2",
    "@types/cookie-parser": "^1.4.2",
    "@types/cors": "^2.8.7",
    "@types/express": "^4.17.8",
    "@types/helmet": "^0.0.48",
    "@types/jest": "^26.0.13",
    "@types/node": "^14.6.4",
    "@types/pino": "^6.3.0",
    "@types/pino-http": "^5.0.5",
    "@types/supertest": "^2.0.10",
    "@typescript-eslint/eslint-plugin": "^4.0.1",
    "@typescript-eslint/parser": "^4.0.1",
    "babel-plugin-module-resolver": "^4.0.0",
    "commitizen": "^4.2.1",
    "cz-conventional-changelog": "^3.3.0",
    "eslint": "^7.8.1",
    "eslint-config-airbnb-base": "^14.2.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-config-standard": "^14.1.1",
    "eslint-import-resolver-typescript": "^2.3.0",
    "eslint-plugin-import": "^2.22.0",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.1",
    "husky": "^4.2.5",
    "jest": "^26.4.2",
    "pino-pretty": "^4.2.0",
    "prettier": "^2.1.1",
    "supertest": "^4.0.2",
    "ts-jest": "^26.3.0",
    "ts-node": "^9.0.0",
    "ts-node-dev": "^1.0.0-pre.62",
    "tsconfig-paths": "^3.9.0",
    "tscpaths": "^0.0.9",
    "typescript": "^4.0.2"
  },
  "dependencies": {
    "amqplib": "^0.6.0",
    "assert": "^2.0.0",
    "bcryptjs": "^2.4.3",
    "class-transformer": "^0.3.1",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "envalid": "^6.0.2",
    "express": "^4.17.1",
    "extendable-error": "^0.1.7",
    "helmet": "^4.1.0",
    "nabbitmq": "^1.0.0",
    "pg": "^8.3.3",
    "pino": "^6.5.1",
    "pino-http": "^5.2.0",
    "reflect-metadata": "^0.1.13",
    "spt-rabbit-helpers": "^1.0.6",
    "tsyringe": "^4.3.0",
    "typeorm": "^0.2.25"
  },
  "config": {
    "commitizen": {
      "path": "cz-conventional-changelog"
    }
  }
}

tsconfig:

{
  "compilerOptions": {
    "target": "es2020",
    "module": "esnext",
    "allowJs": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "strictPropertyInitialization": false,
    "moduleResolution": "node",
    "baseUrl": "./src",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitAny": true,
    "typeRoots": ["node_modules/@types", "@types"]
  },
  "include": ["src", "__tests__"],
  "exclude": ["node_modules"]
}

main:

import 'reflect-metadata';
import express from 'express';
import { RabbitServer } from 'spt-rabbit-helpers';
import validateEnv from 'utils/validateEnvs';
import {
  RabbitMqConnectionFactory,
  ConsumerFactory,
  PublisherFactory,
  RabbitMqConnection,
} from 'nabbitmq';
import { container, singleton } from 'tsyringe';

const factory = new RabbitMqConnectionFactory();
factory.setUri('amqp://localhost:5672');
const ConsumerConnection = await factory.newConnection();
const PublisherConnection = await factory.newConnection();
container.registerInstance('Consumer_Connection', ConsumerConnection);
container.registerInstance('Publisher_Connection', PublisherConnection);
1
  • 12
    Did you ever solve this? Why does it take a masters degree in javasript to use top level await? Commented Jul 14, 2021 at 13:56

5 Answers 5

44

After a lot of searching, I found this solution works perfect:

https://github.com/TypeStrong/ts-node/issues/922#issuecomment-673155000

Just add a "ts-node" block to your tsconfig.json file as below:

{
  "ts-node": {
    "compilerOptions": {
      "module": "commonjs"
    }
  },
  "compilerOptions": {
    "module": "esnext"
  }
}

And it has been documented in the ts-node official page "Via tsconfig.json" part.

This saved hours of my life.

Sign up to request clarification or add additional context in comments.

1 Comment

Oh my god, thank you. This issue happens to me every so often and it's so frustrating to fix, especially when it's a small little script and you just want to get it running.
31

To run ts-node (or plain node for that matter) you need to use "module": "commonjs", "target": "ES2017", otherwise the import/export statements are illegally placed in an IIFE.

So I would suggest using another file called node.tsconfig.json with the following contents:

{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "target": "ES2017" // For NodeJS 8 compat, see https://www.typescriptlang.org/tsconfig#target for more info
    }
}

And then run ts-node with --project ./node.tsconfig.json

6 Comments

It should be noted that the project arg in the ts-node command MUST COME BEFORE the script name. e.g. ts-node --project ./node.tsconfig.json your-script.ts
Apparently ts-node also accepts format {"ts-node": {"compilerOptions": { ... } } } ...in the main tsconfig.json
I couldn't get this answer or the comments to work, even though they looked promising.
Hi @Ryan, Try Looking at the configuration outputted by ts-node --showConfig, maybe ts-node isn’t loading your configuration.
I think I was able to solve my problem after reading bobbyhadz.com/blog/…. I added this to my tsconfig.json: "ts-node": { "compilerOptions": { "module": "commonjs", "target": "ES2017" } },
|
8

I had the same issue and I fixed it by changing the module in tsconfig.json to commonjs and removing the module key in package.json:

// tsconfig.json
{
    "module": "CommonJS",
}

1 Comment

This removes the ability to use top level await, which the OP is trying to accomplish
5

If you are using React, "commonjs" can not be set for TypeScript.

tsconfig.json

{
    "compilerOptions": {
        "module": "esnext"
    }
}

package.json

{
    "type": "module",
    "scripts": {
        "tsnode": "node --loader ts-node/esm --no-warnings"
    },
    "dependencies": {
        "ts-node": "^10.4.0"
    }
}

hello.ts

import * as os from "os"
console.log("os", os);

Two ways to execute the TypeScript file:

  • node --loader ts-node/esm --no-warnings hello.ts
  • npm run tsnode hello.ts

Comments

3

Don't use ts-node, instead use vite-node:

npx vite-node script.ts

Job done, no messing around! No config changes needed!

(It even lets you access node 'fs').

NB: tsx also works.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.