ยท hands on
Write a simple TypeScript script with ESM
I recently wrote a small TypeScript script to generate a Markdown file with a sluggified filename. Since we're now in the era of modern ECMAScript Modules (ESM), I wanted to use this new module system in my TypeScript code. Here's how I did it.
I installed ts-node so I could run my script in a Node.js environment from the command line. The great thing about ts-node
is that it works well with ESM. It comes with a binary called ts-node-esm
that supports loading ECMAScript modules when you run TypeScript code.
Contents
Making TypeScript Work with ESM
Once you've installed ts-node
with npm install
, you can immediately direct it to your script by:
npx ts-node-esm src/main.ts
This ensures that an ECMAScript loader is ready when your code is executed.
Handling File and Folder Paths
In the world of ESM, the usual __filename
and __dirname
constants are not available. So, I found a way to mimic this by using the import.meta property:
import path from 'node:path';
import url from 'node:url';
const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
Using New File Extensions
TypeScript lets you pick different file extensions to tell whether you're using ES modules (.mts
) or CommonJS modules (.cts
).
If you only need to run a single script with the ES module syntax, I recommend using the .mts
extension. It's great in scenarios where you don't want to set up your whole project to use ES modules.
Demo Code
Here's the complete script I developed:
import GithubSlugger from 'github-slugger';
import fs from 'node:fs';
import path from 'node:path';
import url from 'node:url';
const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const args = process.argv.slice(2);
const title = args[0];
const slugger = new GithubSlugger();
const slug = slugger.slug(title);
const filePath = path.join(__dirname, 'content', 'blog', `${slug}.md`);
console.log(`Creating file "${filePath}"...`);
fs.writeFileSync(filePath, '', 'utf8');
console.log(`Created file "${filePath}".`);
It can be ran as follows:
npx ts-node-esm src/new-post.mts "My Post Title"