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 tscs --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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With