DEV Community

Cover image for Node.js, TypeScript and ESM: it doesn't have to be painful

Node.js, TypeScript and ESM: it doesn't have to be painful

Alejandro Oviedo on December 11, 2023

I was thinking into starting a Node.js project from scratch and had an unsettling choice to make: to use ESM or CommonJS. The decision of a few po...
Collapse
 
binarybitbytes profile image
BinaryBitBytes • Edited

Thank you so much for this. I seriously had this problem today when dealing with imports from typescript to js and mjs.

Collapse
 
pablitooficialok profile image
Pablo Chiappetti

Thanks Ale :) Was struggling to understand current state of Node + TS + ESM support and you nailed it here.

Collapse
 
a0viedo profile image
Alejandro Oviedo

Glad it was helpful to you Pablito!

Collapse
 
lirantal profile image
Liran Tal

Nice write-up Alejandro!

Do you find it a better alternative to avoid the "type":"module" and instead just use "main" and "module" as keys (potentially with "exports" too) to avoid the "type" declaration which hardly requires the project to run as a module too?

Collapse
 
a0viedo profile image
Alejandro Oviedo

Thanks @lirantal! I have tried alternatives but in the end type was simpler and easier for people to understand. I feel like "exports" is a rabbit hole where you need to know exactly what you're doing or you are lost.

Collapse
 
lirantal profile image
Liran Tal

Yes agree that exports makes it a bit more harder on discovery :-)
Thanks!

Collapse
 
rajeevdessai profile image
fury-r

I tried the above .swcrc file. It didn't seem to work. I checked on playground got alot of errors.Finally i tried the below config it worked.Thanks for explaining how to do it.
{
"jsc": {
"parser": {
"syntax": "typescript",
},
"target": "es2022",
"loose": false,
"minify": {
"compress": false,
"mangle": false
}
},
"module": {
"type": "es6"
},
"minify": false,
"isModule": true
}
.swcrc

Collapse
 
crazyjat profile image
Jeff Tillwick

Can someone, for the love of all that is good, please explain to me in a way that actually makes sense WHY anyone would want to import something with an extension? PLEASE! Help me understand why ANYONE would want to do this?

Collapse
 
hatch33 profile image
Uroš Čeh

Have you tried using ts-node/register instead of tsx?

Collapse
 
a0viedo profile image
Alejandro Oviedo

I did, for me tsx seems simpler to use.

Collapse
 
cforcloud profile image
kantha g ☁️

Did you happen to try unjs.io/packages/jiti together with unjs.io/packages/listhen

Collapse
 
a0viedo profile image
Alejandro Oviedo

I have not! I might give them a try but so far I didn't had major issues with the approach described here

Collapse
 
romakyrnis profile image
Roman

Thank you!
I've run ts code using @swc-node/register/esm like so "NODE_ENV=dev node --loader @swc-node/register/esm src/index.ts"