ts-node: `ts-node` fails when ES Modules are in the dependency graph in Node.js 13+
I basically detailed the issue in this comment: https://github.com/TypeStrong/ts-node/issues/155#issuecomment-570120923
It’s a chicken-and-egg-like problem:
- If we use
module: 'commonjs'
, then if any TS files import ES Modules (indirectly in their dependency graph), then Node throws an error because CommonJS modules can not import ES Modules. - If we change to
module: 'esnext'
, then the errors from the previous point go away, but now the.js
file that is loadingts-node
and calling something likerequire('typescript-entry-point.ts')
will have a similar issue, because the call torequire('typescript-entry-point.ts')
will try to load an ES Module. - Finally, if we convert the
.js
file into an ES Module, we can not convertrequire('typescript-entry-point.ts')
intoimport 'typescript-entry-point.ts'
because now ES Modules don’t handle.ts
extensions (at least not out of the box, and it seems the old require hooks don’t operate on these new identifiers)
At the moment, I’m sort of stuck, because I have dependencies in my dependency tree that are ES Modules.
The only workaround I can think of is to compile everything to .js
files (ES Modules) and avoid to use ts-node.
I wonder if a combination of allowJs
and ignore
so that it compiles JS files would help. I haven’t tried that yet.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 139
- Comments: 80 (4 by maintainers)
Links to this issue
- node.js - How to run TypeScript files from command line? - Stack Overflow
- Can't run my Node.js Typescript project TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /app/src/App.ts - Stack Overflow
- package.json - ts-node execute typescript with module import and module defined - Stack Overflow
Commits related to this issue
- Fix the WebAssets build There's an issue using ts-node when ES Modules are in the dependency graph in Node.js 13+. The fix is to remove this line. https://github.com/TypeStrong/ts-node/issues/935 — committed to haacked/mirrorsharp by haacked 4 years ago
- Fix the WebAssets build when using Node.js 13+ When I run `npm run-script build` in the `WebAssets` directory, the build fails with the following error. ``` TypeError [ERR_UNKNOWN_FILE_EXTENSION]: U... — committed to haacked/mirrorsharp by haacked 4 years ago
- Remove top-level async. It's unsupported now, for some reason, despite working before. https://github.com/TypeStrong/ts-node/issues/935 — committed to mhansen/hledger-vscode by mhansen 3 years ago
- fix: compile to commonjs (#369) Publishing `@guardian/cdk` in ESM format is tricky as additional tooling required by consumers such as [ts-node](https://github.com/TypeStrong/ts-node/issues/1007) (se... — committed to guardian/cdk by akash1810 3 years ago
- Support for ECMAScript Modules This adds support to import this package from ECMAScript Modules. The changes are fairly broad since some non-compliant tooling and experimental features were relied on... — committed to laverdet/ip-address by laverdet 2 years ago
- Fix inability to run scripts on 'ts-node' Source: https://github.com/TypeStrong/ts-node/issues/935#issuecomment-913179458 — committed to EvitanRelta/markgh by EvitanRelta 2 years ago
- Fix inability to run scripts on 'ts-node' Source: https://github.com/TypeStrong/ts-node/issues/935#issuecomment-913179458 — committed to EvitanRelta/markgh by EvitanRelta 2 years ago
- Fix issue importing ESM modules Ref: https://github.com/TypeStrong/ts-node/issues/935#issuecomment-1480408750 — committed to thoughtbot/belt by stevehanson a year ago
It seems that
ts-node
fails to run with"module": "esnext"
in thetsconfig.json
and"type": "module"
in thepackage.json
with the following error:Sorry to say this but the way ESM was added to Node is a total disaster and many thousands of hours wasted for developers worldwide. 😕
If you’re still facing the issue with module ESNext, this saved my day:
If you must keep “module”: “ESNext” for tsc, webpack, or another build tool, you can set an override for ts-node.
Source: https://www.npmjs.com/package/ts-node?activeTab=readme#commonjs
It is amazing that 3 years after this was reported I am still facing this issue with no solutions tried would solve but hours spent and wasted.
Just add
module: commonjs
intsconfig.json
and removetype: moudle
inpackage.json
works for me.tsconfig.node.json
package.json
server/index.ts
If anyone is coming to this issue like I did I was able to get TS working inside a project with
"type": "module"
throughnodemon
by adding anodemon.json
with this in it:Essentially replacing the default
"execMap"
of"ts": "ts-node"
… in case it matters mytsconfig.json
like:With that my
"dev"
script inpackage.json
is just"nodemon src/index.ts"
and it all seems to work!Well, looks like
@K-FOSS/TS-ESNode
does work with Node 13.7. That’s amazing. I’ll get to work on porting this directly intots-node
hopefully sometime this weekend. Work has been busy, not enough time for personal coding.I’m closing this issue because the feature has been implemented, and feedback is tracked by #1007.
same issues occurring right now
@menangaTech I was trying to use formadata-node, which in an ESM-only package. Here’s a snippet that causes problems:
I fixed it by having
"type":"module"
in my package.json file and the following tsconfig.json:The important parts are the
module
andts-node
settings@meabed are you sure it’s not working? I just tried and and it works correctly (must use node v14.3.0+ with tla flag)
tsconfig.json
package.json
index.ts
You better stop using ts-node and start using tsx unless you really need to use the emit decorators metadata option of typescript if you’re using something like TypeORM (you can still use tsx though).
Same here:
tsconfig.json -> compilerOptions:
package.json:
"type": "module"
Reason for the entries above:
Top-level ‘await’ expressions are only allowed when the ‘module’ option is set to ‘esnext’ or ‘system’, and the ‘target’ option is set to ‘es2017’ or higher. ts(1378)
@cspotcode thanks for a voice of reason 😃 I think the blame is spread. Firstly, I think Node made it look like ESM is ready for prime time and then some library authors jumped the gun by deprecating Common.JS builds. More reasonable library authors ship both ESM and Common.JS.
Not sure if this was a general expression of frustration, or was directed specifically at the nodejs team.
If the former, I tend to think the blame also rests largely on the developer community for moving libraries to ESM before it was ready.
If the latter, I’m not a part of the node team, but you can reach them here:
https://github.com/nodejs/node/discussions https://github.com/nodejs/loaders
Same error, none of the above solutions worked.
typescript
:4.9.5
ts-node
:10.9.1
Yes, this issue happened right after I added “type”: “module” to the package.json in an attempt to not create the .mjs files. I am on node 14
Any update on this? ts-node will always fail when the
"type": "module"
is in package.jsonI was trying to setup this typescript for apollo-server and I was getting the same error, this is how my tsconfig.json file end up:
For some people who get to this point, if you add to your tsconfig.json, it allows the .js files to resolve.
file.ts
another.ts
This is released as an experimental feature in ts-node v8.10.0. Please test and share your feedback in #1007.
You will probably want to enable “transpileOnly” in your tsconfig for better performance. However, we do support typechecking if you want that.
I’d love to give that a shot. I’ll take a crack at it sometime this weekend.
@KristianFJones If you’re interested I’d love to land a PR in
ts-node
with this functionality.I created a proof of concept for using the current version of the --experimental-loader feature to transpile typescript files right before node loads it and then give node the now ESNext Javascript code with the SyntheticModule VM feature. It’s fairly hacky right now but it made for a fun 6 hour session: https://github.com/KristianFJones/TS-ES-Node
Please, can somebody explain for dummy how to use ts-node imports. Whatever combination I’m trying to use resulting in some errors either
Cannot use import statement outside a module
or any other import problem…Trivial setup: package.json
tsconfig.json
code app/translate.ts
Error
Will really appreciate for help.
This issue still happens :
try gulpfile.ts
tsconfig.json
That globby package has
in its package.json.
And importing it cause
If I don’t import it, I get no errors.
@cspotcode Thanks for your feedback 😃. microbundle which uses autoprefixer which uses colorette works with plain node. The error only happens if ts-node is involved, so to me it looks like ts-node obviously has to be “involved” ^^.
This is the trace: at Module._extensions…js (internal/modules/cjs/loader.js:1217:13) at Object.require.extensions.<computed> [as .js] (XYZ/node_modules/ts-node/src/index.ts:851:44) at Module.load (internal/modules/cjs/loader.js:1050:32) at Function.Module._load (internal/modules/cjs/loader.js:938:14) at Module.require (internal/modules/cjs/loader.js:1090:19) at require (internal/modules/cjs/helpers.js:75:18) at Object.<anonymous> (XYZ/node_modules/autoprefixer/lib/autoprefixer.js:5:17) at Module._compile (internal/modules/cjs/loader.js:1201:30) at Module._extensions…js (internal/modules/cjs/loader.js:1221:10) at Object.require.extensions.<computed> [as .js] (XYZ/node_modules/ts-node/src/index.ts:851:44)
Look’s like I know what I’m doing this weekend.
Yeah I managed to track it down to Chai v5 becoming ESM only. Too bad eh!
Thanks this actually worked @erick2014
still having the same issue. @mysterycommand’s solution doesnt work for me either. trying the same thing as the original author of this thread. Attempting to import a library with es6 modules in a ts project and trying to run it with
ts-node <path-to-entry-point.ts>
my tsconfig.json is as follows@katywings Thanks for the details. Do you have allowJs turned on? What’s the node version? Can you send a minimal reproducible example?
Colorette declares that
require()
should be loadingindex.cjs
, notindex.js
. https://unpkg.com/browse/colorette@1.2.1/package.jsonBut the stack trace shows that it’s trying to load
index.js
.That leads me to suspect a node bug that manifests when a custom
require.extensions['.js']
handler is installed. But without a reproduction, there are too many unknowns: I don’t know the versions of libraries or of node and I don’t know the ts-node nor ts configurations.I think your issue is subtley different than the ones described in this ticket, because ESM should not come into play. Colorette is telling node that it can be loaded as CommonJS but somehow that’s being ignored.
Feel free to file this as a separate ticket if you want.
@meabed that is also explained in the “Usage” section of #1007 and in node’s ESM documentation. Remember that a lot of things are controlled by node and TypeScript. At the end of the day, we’re using TypeScript to convert your code into JS that’s run by node, and we need to remain compatible with
tsc && node
. A great way to answer these questions for yourself is to try usingtsc && node
and see what is and is not allowed.Thanks @cspotcode - it works perfectly fine 😃 Thanks alot! the missing part was importing the file with .js extension
thats awesome it works 😃 a follow up question - do you think it would be doable without the extension import soon 👍 just trying to see should we all imports to .js to use the top level await or we hold a bit if its coming soon. Best regards.
@meabed This is a problem with your code. The solution is explained in the “Usage” section of the documentation here: #1007. Please read it fully, because it also explains some other details you need to be aware of.
yea please - this need a quick fix - no one can use top-level-await with ts-node 😦
Removed the
globby
requirement. Module has been published on NPM https://www.npmjs.com/package/@k-foss/ts-esnode zero dependencies other then peer dependency on TypeScript. NPM reports unpacked size of 8.66 kB. Should hopefully be a drop in replacement forTS-Node
for now.Okay, made a few small changes and fixes. It’s now able to handle external modules that have the TSLib import helper without requiring refactoring existing imports. The
TS-ESNode
loader hook can be dropped into existing projects and just work. Hopefully! I just tested it on my main Application template that uses TypeORM & TypeGraphQL withtsconfig.json
set to use ESNext as target and modules and it all just works. Transpiled code is all using imports and exports with Node V14 in Module mode.Been busy, here is a proof of concept using the
transformSource
hook. Supports relative imports of.ts
and.tsx
without requiring extensions. https://github.com/K-FOSS/TS-ESNode