DEV Community

eiymba
eiymba

Posted on • Updated on

Compiling TypeScript to ESNext for Back-End node.js Apps

Let's keep it short and sweet! 🍬

Contents

Node Version
Set Node To Use Modules
TypeScript Compiler Options
Change Your Imports
Why Do This?

Node Version

You'll need node version 13 or higher. We'll be using Node Version Manager to handle this.

nvm install latest
Enter fullscreen mode Exit fullscreen mode
nvm ls
Enter fullscreen mode Exit fullscreen mode

Important! Note the latest version, then use it for the following command:

nvm use <version>
Enter fullscreen mode Exit fullscreen mode

Replace <version> with the one installed on your machine.

Note: Proceed with caution when using the latest version over the LTS version in production.
On Windows 10, I recommend downloading chocolatey, then use chocolatey to install Node Version Manager; commonly referred to as "nvm".
Click here for installation on Unix machines.

Set Node To Use Modules

Add the following line to your package.json file.

"type": "module"
Enter fullscreen mode Exit fullscreen mode

TypeScript Compiler Options

compilerOptions needs target, module, and moduleResolution options to be changed in your tsconfig.json file.

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node"
  }
}
Enter fullscreen mode Exit fullscreen mode

Note: remove the resolveJsonModule option if you have set it. If you need to read JSON data, either use fs.readFileSync at the start of your program, or utilise the new promise variant; await fs.readFile.

Change Your Imports

For simplicity, here are some rules:

  • All your imports must end with a .js file extension, even if they end with .ts in your source code. As far as I know, Visual Studio Code will pick up the correct TypeScript file.
  • Make sure your compiled JavaScript files and your TypeScript source files are equal in depth from your project's root folder. For example, if your TypeScript source files are stored in ./src then your compiled JavaScript files should be stored in ./out.

old:

import { myModule } from './src/modules'
myModule()
Enter fullscreen mode Exit fullscreen mode

new:

// If myModule is exported as a named function or function variable.
import { myModule } from './src/modules/myModule/index.js'
myModule()
Enter fullscreen mode Exit fullscreen mode

or:

// If myModule is exported as the default module.
import * as myModule from './src/modules/myModule/index.js'
//@ts-ignore
myModule.default.myModule()
Enter fullscreen mode Exit fullscreen mode

Note: Your file doesn't need to be called index.js, but the .js file extension must be present.

Done!

Why Do This?

  • No more asynchronous generators!
  • Aligns your source code closer to your compiled code.
  • Easier to debug in production, or where source maps aren't available.
  • You can afford to experiment with the latest APIs.
  • Reduces dependencies (Babel and CommonJS).
  • Performance gains.
  • You just need a compiler which removes the types from your TypeScript files.
  • You use the debug feature in Visual Studio Code and it already compiles for you.
  • Your life depends on it for some unknown reason.

Oldest comments (2)

Collapse
 
bichotll profile image
Jaume Tarradas Llort

There is something important to point out tho. ts-node does not seem to work yet with ES modules.
Many people use ts-node nowadays and I came across this very issue:

github.com/TypeStrong/ts-node/issu...

I'd recommend using something like:

  "scripts": {
    "dev": "concurrently \"npm run build:watch\" \"nodemon dist/index.js\"",
Enter fullscreen mode Exit fullscreen mode

Please correct me if I'm wrong. Thanks.

Collapse
 
eiymba profile image
eiymba

I have no idea, sorry. I don't use ts-node. Instead, I create launch and task configurations in VS Code, which recompiles and restarts the debugging session on save.