Now Reading: TypeScript levels up with type stripping

Loading
svg

TypeScript levels up with type stripping

NewsJanuary 22, 2026Artifice Prime
svg3

TypeScript is usually described as a superset of JavaScript, meaning all valid JavaScript is also valid TypeScript. With a few notable exceptions (like Enums and namespaces), it is possible to go through a program, delete the type information, and arrive at a perfectly legitimate JavaScript program. This is type stripping, an alternative to transpilation.

Now there’s a move to add type stripping to the core language, which would make it even easier to run your TypeScript programs as JavaScript.

Similar to type erasure in Java, type stripping would make it possible to execute a cheap text replacement of type information at runtime, rather than a heavier compile step later. Modern runtimes like Deno and Bun have supported this capability natively for some time, but type stripping really hit the enterprise mainstream in Node.js.

Starting in Node 22.6, released early last year, the JavaScript runtime can execute TypeScript directly. Node’s --experimental-strip-types flag erases, on the fly, all the parts of a TypeScript program that are not compatible with Node.

We’ll start with a look at how this feature works in Node, then discuss the ramifications of adding something similar to TypeScript.

Type stripping in Node

Consider the following TypeScript program:

// animal.ts
interface Animal {
  name: string;
  winged: boolean;
}

function move(creature: Animal): string {
  if (creature.winged) {
    return `${creature.name} takes flight.`;
  }
  return `${creature.name} walks the path.`;
}

const bat: Animal = {
  name: "Bat",
  winged: true
};

console.log(move(bat));

If we try to run this directly in Node, we get an error:

$ node animal.ts
C:\Users\matth\node\animal.ts:1
interface Animal {
          ^^^^^^

SyntaxError: Unexpected identifier 'Animal'

But if we run it with the new --experimental-strip-types flag, it works:

$ node --experimental-strip-types animal.ts
Bat takes flight.

Type stripping removes all the TypeScript-specific syntax, leaving something like the following:

// The interface is gone (replaced by whitespace)
                                  //
                                  //
                                  //

function move(creature) {         // ': Animal' and ': string' are stripped
  if (creature.winged) {
    return `${creature.name} takes flight.`;
  }
  return `${creature.name} walks the path.`;
}

const bat = {                     // ': Animal' is stripped
  name: "Bat",
  winged: true
};

console.log(move(bat));

Node’s --experimental-strip-types flag has inspired changes to the TypeScript spec itself, starting with the new erasableSyntaxOnly flag in TypeScript 5.8. Having the experimental flag available at runtime is one thing, but having it built into the language is quite another. Let’s consider the broader effects of this change.

No more source maps

For debugging purposes, it is essential that the types in our example are replaced with whitespace, not just deleted. That ensures the line numbers will naturally match-up between runtime and compile time. This preservation of whitespace is more than just a parser trick; it’s a big win for DX.

For years, TypeScript developers relied on source maps to translate the JavaScript running in the browser or server back to the TypeScript source code in their editor. While source maps generally work, they are notorious for being finicky. They can break and fail to map variables correctly, leading to problems where the line number in the stack trace doesn’t match the code on your screen.

With type stripping, the code running in Node is structurally identical to the code in your editor, line-for-line. Line 10 in your IDE is line 10 in the runtime. This eliminates the need for source maps during development, so the stack traces are always accurate, and your breakpoints always hit. Perhaps most importantly, having type stripping built into TypeScript eliminates an entire class of artifacts (source maps) from the build process.

This reinforces the realization that type information is not really a runtime factor but one that matters at development time. We want the guardrails in place while we are coding in the IDE, but after that, we can replace types with whitespace. Then the program can just run—with no build or compile step required.

What we lose to type stripping

With any change like this, there will be casualties. Other than source maps (which few will miss) type stripping in TypeScript mainly affects features that are not amenable to erasure:

  • Enums
  • Namespaces
  • Class parameter properties
  • import =

While some say these features are outside of TypeScript’s scope, they are all valid TypeScript constructs. They cannot be directly whitespaced out and require a compilation step to translate into valid JavaScript; therefore, the flag to enable only erasable syntax will throw an error when encountering them.

The TypeScript 5.8 announcement showed the following errors when using the flag:

// ❌ error: A namespace with runtime code.
namespace container {
    foo.method();

    export type Bar = string;
}

// ❌ error: An `import =` alias
import Bar = container.Bar;

class Point {
    // ❌ error: Parameter properties
    constructor(public x: number, public y: number) { }
}

// ❌ error: An enum declaration.
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

Most of these are self-evident, but it’s worth noting that in parameter properties, the problem is that they require the compiler to inject actual assignment logic (this.x = x) into the constructor, which a simple “strip” operation cannot do.

The ‘Bridge of Zod’

It isn’t new for TypeScript to lose the type information by the time it’s running as JavaScript. It is either removed by the compiler or by stripping. This creates a problem if you need access to type information (for example, if you need to check that a request parameter is a string). The Zod library addresses the problem, and also provides a simple replacement for Enum.

Because type stripping aggressively removes all type information, it underscores that TypeScript cannot validate your API responses or user inputs at runtime. If you define an interface, Animal, that interface ceases to exist the moment Node runs your file.

This is where libraries like Zod can be the perfect partner to type stripping.

Since Zod schemas are defined using standard JavaScript objects and functions, they survive the stripping process completely intact. They provide the runtime safety that TypeScript “types as comments” cannot.

Also, Zod offers a direct solution to the casualties I mentioned above, particularly Enums. Since TypeScript Enums are banned in a type-stripping environment (because they generate code), developers have used Zod Enums instead. They exist as real JavaScript objects at runtime, but  they can still export the static type definitions your IDE loves.

In that case, the workflow might look something like this:

  1. Define a Zod schema (the runtime JavaScript stays).
  2. Infer a TypeScript type from that schema (the static TypeScript is stripped).
  3. Run the code without a build step, knowing your validation logic is still there.

Let’s run through a quick example to see how this works. In the code below, Zod “infers” the type at runtime, using JavaScript, and then exposes a TypeScript type at “type-checking time” (like in the IDE). To start, here’s a Zod schema:

const AnimalSchema = z.object({ 
  name: z.string(), 
  winged: z.boolean(), 
});

Note that the schema is just a JavaScript object with special functions used for validating instances. This object itself gives you everything you need for the runtime checks. To handle the compile-time, you add a line like so:

type Animal = z.infer;

This line will be removed by the type-stripper. This is a very clever piece of engineering; it boils down the whole role of TypeScript, enforcing the Animal type to a single line that smoothly bridges between compile time and runtime.

Type stripping and the future of JavaScript

Type stripping has all kinds of interesting ramifications, including for the future of JavaScript, as the JavaScript design team continues to contemplate absorbing type definitions (in one form or another) into the language itself.

Efforts have been underway for some time to make JavaScript do types. Most notably, the TC39 proposal, officially “Type Annotations,” also known as “Types as Comments.” The current era of type stripping is something of a bridge toward the possibility paid out by TC39. The JavaScript types proposal is still in stage 1, but changes to how we use TypeScript in practice could reawaken its ideas.

The basic idea in the type annotations proposal is very similar to type stripping (and comes with the same caveats for things like Enum), but instead of stripping, the idea is to comment out the type info. The runtime engine entirely ignores the type syntax, while the development-time engine (the IDE or linter) uses it to enforce types.

It’s worth noting that the JavaScript proposal has more than just TypeScript in mind. It also explicitly mentions the Closure compiler and Flow as targets. The end result would likely be the replacement of all three technologies with JavaScript.

As the specification correctly notes, the desire for static types in JavaScript has consistently ranked as the most in-demand “missing feature” in the annual State of JavaScript surveys.

The browser gap

Server-side runtimes like Node, Deno, and Bun are embracing type stripping but web browsers cannot yet embrace it. Both Chrome and Safari will crash the moment they encounter a type annotation.

For now, this creates a split in the ecosystem: A “no-build” utopia for the back end, but a continued reliance on build tools like Vite or webpack for the front end. This is exactly why the TC39 proposal for JavaScript is the final piece of the puzzle. Until browsers can natively ignore type syntax, universal type stripping remains out of reach. (This is a bit reminiscent of when the browser and server diverged on import syntax.)

Type stripping and the ‘no build’ future

Ultimately, type stripping is about much more than a Node flag or even a TypeScript feature. It represents a shift in how we view our tools. For a decade, developers have accepted that enterprise-grade JavaScript requires a heavy, complex build pipeline.

Features like --experimental-strip-types and the TC39 JavaScript proposal challenge that assumption. They point toward a future where the friction between writing code and running it is greatly attenuated. By treating types as useful dev-time comments, rather than compiler instructions, we get the safety we need while reducing the burden of complexity. That is a major level up for TypeScript, and for the technologies that will follow.

Original Link:https://www.infoworld.com/article/4116375/typescript-levels-up-with-type-stripping.html
Originally Posted: Thu, 22 Jan 2026 09:00:00 +0000

0 People voted this article. 0 Upvotes - 0 Downvotes.

Artifice Prime

Atifice Prime is an AI enthusiast with over 25 years of experience as a Linux Sys Admin. They have an interest in Artificial Intelligence, its use as a tool to further humankind, as well as its impact on society.

svg
svg

What do you think?

It is nice to know your opinion. Leave a comment.

Leave a reply

Loading
svg To Top
  • 1

    TypeScript levels up with type stripping

Quick Navigation