简体   繁体   中英

"require() of ES Module [...] is not supported" when using typescript

My setup is as follows:

I have a package.json file:

{
  "name": "discord-app-test",
  "version": "1.0.0",
  "main": "src/index.ts",
  "license": "ISC",
  "scripts": {
    "dev": "nodemon --exec \"yarn start\" --watch src --ext ts,json --ignore *.test.ts",
    "start": "ts-node ."
  },
  "dependencies": {
    "dotenv": "^10.0.0",
    "node-fetch": "^3.0.0"
  },
  "devDependencies": {
    "@types/node": "^16.11.6"
  }
}

I have no tsconfig.json file as I never need it, normally. Though, somehow when using the node-fetch package, I get this error saying " require() of ES Module [...] is not supported " even though I am importing it with the ES6 syntax:

import fetch from 'node-fetch';

I have tried specifying "type": "module" in my package.json, but then I got the error " Unknown file extension ".ts" for [...] ".

You probably want to use "type": "module" because this is the new way to import stuff in node. With this flag you tell node to use ESM for imports which is the syntax you've used in your question.

ESM is fairly new, so most tools have an opt-in for this and so does ts-node , you've to add the --esm argument.

$ ts-node --esm ./index.ts

Running this still fails with

$ ts-node --esm ./index.ts
ReferenceError: exports is not defined in ES module scope
    at file:///path/to/index.ts:5:23
    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

The error is because of tsc s --module default which ts-node internally uses.

--target : Default: ES3

--module : Default CommonJS if target is ES3 or ES5,ES6/ES2015 otherwise.

https://www.typescriptlang.org/docs/handbook/compiler-options.html

tsc will transpile scripts to CommonJS, because --target default is ES3 and then the --module default is CommonJS.

You can check this by manually running the TypeScript compiler.

index.ts

import fetch from "node-fetch";
fetch("https://example.org");
$ tsc ./index.ts

index.js (created by tsc)

"use strict";
exports.__esModule = true;
var node_fetch_1 = require("node-fetch");
(0, node_fetch_1["default"])("https://example.org");

The.ts file was transpiled for CommonJS (it uses require ).

When you define "type": "module" inside your package.json , you tell node to use the new import syntax, but tsc ignores that and still outputs it in the old format.

If you want to use the new import syntax natively in node, then you can fix the problem by defining the module to nodenext which describes the ESM support for node.

$ tsc --module nodenext ./index.ts

index.js (created by tsc)

import fetch from "node-fetch";
fetch("https://example.org");

The easiest way to configure the --module in for ts-node is to create a tsconfig.json with the following content:

{
  "compilerOptions": {
    "module": "nodenext"
  },
  "include": ["*.ts"]
}

Now after configuring the module, you can run ts-node and it'll hopefully work well.

$ ts-node --esm ./index.ts

Here you can read more about ESM support in ts-node : https://github.com/TypeStrong/ts-node/issues/1007

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM