See some of the latest experimental features in Node.js: run TypeScript code directly in Node.js without transpiling, built-in SQLite support and glob file search.
In my previous post, I shared three Node.js features you didn’t know about, which doesn’t do justice to the numerous APIs added to the Node.js runtime in the last three years. I can’t address all of them in one post, so I’ll focus on two more in this post, and do a separate independent post for APIs that merit a longer, detailed blog post.
Let’s dive right in.
My favorite use for the Bun JavaScript runtime is the ability to run TypeScript code without the need for extra packages and configuration. JavaScript developers are rapidly moving to writing code using TypeScript, as you can see from this GitHub trend report.
Instead transpiling TypeScript code using tools like tsc or esbuild, or using a runner like ts-node, you can now run TypeScript code directly in Node.js. Node.js introduced an experimental flag for this in version 22.6.0 Here’s how to use it:
node --experimental-strip-types index.ts
The --experimental-strip-types
flag tells Node.js to strip the type annotations from the TypeScript code before running it. Node.js doesn’t do any type checking, and it’ll replace inline type annotations with whitespace. Also, it’ll execute only files that don’t contain features that require transformation, such as enums or namespaces.
To enable the transformation of such features, use the flag --experimental-transform-types
.
node --experimental-transform-types index-with-enums.ts
The --experimental-transform-types
flag implies --experimental-strip-types
and --enable-source-maps
, and is available in Node.js starting from version 22.7.0.
Running TypeScript natively with those flags doesn’t yet support tsconfig.json settings such as paths or converting newer JavaScript syntax to older standards. When this feature becomes stable, it’ll be able to run TypeScript fully well, just like you can with Deno or Bun.
Although SQLite is the most deployed and used database, it recently became the talk of the town and is fast becoming the preferred for many web developers. I think Rails 8 made it the default database within the framework. I think this made the Node.js team consider natively supporting it. There are various packages for SQLite, but having it built in eliminates the need to add yet another library or worry about which SQLite library to use.
This feature is still experimental and was added to Node.js in version 22.5.0. Here’s an example from the documentation:
import { DatabaseSync } from "node:sqlite";
const database = new DatabaseSync(":memory:");
database.exec(`CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT) STRICT`);
const insert = database.prepare("INSERT INTO data (key, value) VALUES (?,?)");
insert.run(1, "hello");
insert.run(2, "world!");
const query = database.prepare("SELECT * FROM data ORDER BY key");
console.log(query.all());
The example shows the basic usage of the node:sqlite
module to open an in-memory database, write data to the database and then read the data back. You need the --experimental-sqlite
flag when you run that code. That means executing the code with node --experimental-sqlite data.js
will include the node:sqlite
module to the runtime, and omitting it will cause the application to fail.
OK. I know I said I’d show you just two features, but if you often work with the file system API you’ll appreciate this one. The glob search API allows you to search for files using patterns, similar to how you might use wildcards in a shell. This can be incredibly useful for tasks like finding all files of a certain type, or files that match a specific naming pattern within a directory.
Node.js 22.0.0 came with the glob
and globSync
API functions for this purpose. It allows you to specify a pattern and a set of options, and it returns an array of file paths that match the pattern.
Here’s an example:
import { glob } from "fs/promises";
const testFiles = await glob("**/*.test.js");
console.log(testFiles);
This will return the path to every file that ends with test.js
in the current working directory. You can specify the working directory to run the pattern matching using the cwd
option. For example:
import { glob } from "fs/promises";
const testFiles = await glob("**/*.test.js", {cwd: "/users/"});
console.log(testFiles);
This post explores three recent Node.js features: running TypeScript natively, SQLite support and glob file search.
Node.js now allows running TypeScript code without additional tooling, by using experimental flags like --experimental-strip-types
and --experimental-transform-types
, though full support is still developing. Native SQLite support in Node.js eliminates the need for external libraries, allowing simpler database operations with the node:sqlite
module. Lastly, the new glob search API offers a powerful way to find files using patterns, enhancing file system operations.
Although they’re all experimental features, they demonstrate Node.js’s continuous evolution, that is, catering to modern development needs while maintaining backward compatibility for legacy systems.
Peter is a software consultant, technical trainer and OSS contributor/maintainer with excellent interpersonal and motivational abilities to develop collaborative relationships among high-functioning teams. He focuses on cloud-native architectures, serverless, continuous deployment/delivery, and developer experience. You can follow him on Twitter.