Node.js Now Has TypeScript Type Stripping On By Default
-
Eric McCarthy
-
-
2 min read -
nodejs
Despite keeping up better with my RSS feed reader lately, I still missed that Node.js v22.18.0 enables TypeScript type stripping by default! Apparently it has also been enabled in v24 since its initial release.
This is great news, because it means that with some important caveats, it is now
possible to run TypeScript natively in Node without needing to specify the --experimental-strip-types
flag. The caveats boil down to the fact that not every TypeScript language feature
can be cleanly stripped to create valid JavaScript — a small handful of features
require the TypeScript compiler to generate JavaScript code in order to fully
function.
Luckily, in TypeScript v5.8 they introduced the --erasableSyntaxOnly option. This raises errors when you use one of these features that would cause Node.js to throw a JS parse error even after type stripping.
The full list of these non-erasable language features is thankfully small, and, in my usage of TypeScript, quite manageable:
namespaces andmodules with runtime codeimport =aliases-
Parameter properties in class constructors (the shorthand where
class { constructor(readonly foo: Bar) {} }auto-creates afooprop) enumdeclarations
I don’t think I’ve ever used executable code in a namespace or a
module — the only time I use those is if I need to extend global or
package types. I don’t think I’ve ever used
import = aliases. And I can easily live without parameter properties.
Lack of enums is probably the toughest pill to swallow. But the TypeScript docs
for enums have a good suggestion — instead of creating an enum create an object
with as const:
export const Direction = {
Up: 1,
Right: 2,
Down: 3,
Left: 4,
} as const
export type DirectionEnum = (typeof Direction)[keyof typeof Direction]
Hopefully this proposal for an as enum assertion gets some traction, since
it would be nice to not need an extra [Name]Enum type.
There are two other TS options that are helpful for running type-stripped TS in
Node:
rewriteRelativeImportExtensions and verbatimModuleSyntax. The former helps ensure you can use .ts
extensions in your import statements, and the latter avoids surprises
from top-level side-effects when importing a TS module.