TypeScript Dominance Splinters JavaScript Runtimes, Malware Chooses Deno
A ransomware gang betting on Deno for malware delivery exposes the deep fragmentation between Node, Bun, and Deno in how they handle TypeScript, a divide that matters more than raw performance.
In March 2026, the LeakNet ransomware gang began deploying a malware loader written on the Deno runtime, leveraging the ClickFix social-engineering technique to gain initial access into corporate environments. Bleeping Computer reported that the loader uses the open-source Deno runtime for JavaScript and TypeScript, a choice that surprised many in the security community, not because Deno is inherently insecure, but because threat actors are now treating the runtime ecosystem the same way enterprise teams do: as a set of differentiated platforms worth evaluating, exploiting, and betting on.
The ransomware story is lurid, but it captures something real about where the JavaScript world sits in mid-2026. TypeScript has cemented its position as the default language of the web. The State of JavaScript 2025 survey, published in March 2026, showed TypeScript continuing to dominate, more than 70% of respondents reporting it as their primary language for new projects. But the language's victory has produced an awkward second act. The three major runtimes, Node.js, Bun, and Deno, each execute TypeScript differently, and the differences are no longer about sub-millisecond startup benchmarks. They are about philosophy: what a runtime owes its users, what safety means, and whether TypeScript's types should exist at runtime at all.
The timing could hardly be more charged. On April 21, 2026, Microsoft officially announced the TypeScript 7.0 Beta, built on a Go-based foundation that the company says is often ten times faster than the JavaScript-based TypeScript 6.0 compiler. TypeScript 6.0, released in March, was the final version built on the original self-hosted codebase. The port to Go, led by Anders Hejlsberg and the TypeScript team, represents a massive engineering investment, one that implicitly acknowledges a truth the runtime fragmentation has been shouting for years: the TypeScript compiler, for all its elegance, had become a bottleneck that no single runtime could solve alone.
The promise of TypeScript 7.0 is straightforward. Faster builds, faster editor feedback, faster CI pipelines. But the compiler speedup lands into an ecosystem where the runtimes have already diverged on a more fundamental question: should TypeScript even need a compiler? Bun, the youngest of the three, was designed from the start to run TypeScript files directly, without a separate compilation step. It strips type annotations at parse time and executes the resulting JavaScript immediately. For developers who came up in the era of tsc --watch and source maps that never quite lined up, the experience feels like magic. For teams with large monorepos and thousands of test suites, it feels like reclaimed hours.
Node.js, the incumbent that still runs the vast majority of production JavaScript workloads, took a more cautious route. Starting with Node.js 23.6 in early 2025, the runtime introduced experimental support for TypeScript via the --experimental-strip-types flag, a deliberate choice of name that signals exactly what Node is doing: treating type annotations as whitespace, erasing them before execution, and making no attempt to type-check. The approach is philosophically aligned with the broader movement toward type stripping, which InfoWorld's Matthew Tyson described as a way to keep stack traces accurate and workflows clean: "By treating types as whitespace, modern runtimes are unlocking a no-build TypeScript." Node's version is opt-in, experimental, and explicitly not a replacement for tsc in CI. But its existence shifts expectations. If the world's most widely deployed server-side JavaScript runtime can strip types, the compiler begins to look optional, not for correctness, but for execution.
Deno, created by Node.js founder Ryan Dahl, has taken yet another path. Deno 1.0 launched in 2020 with first-class TypeScript support built in, compiling files internally before execution. Its pitch was always security-first: a permissions system that gates file system access, network requests, and environment variables behind explicit flags. When Deno 2.5 arrived in October 2025, it added permission sets and test API hooks, features that reinforced the runtime's identity as the safe, batteries-included option for teams who want their JavaScript to feel like a systems language. Deno compiles TypeScript by default. It does not strip types lazily. It checks them.
This is what makes the LeakNet story so disorienting. The Deno runtime was marketed on safety. Its permission model was supposed to prevent exactly the kind of damage ransomware inflicts: no file writes without --allow-write, no network access without --allow-net. And yet attackers chose it. The Bleeping Computer report notes that the Deno-based loader uses ClickFix, fake CAPTCHA pages that trick users into executing malicious PowerShell commands, as its initial access vector. The runtime itself is not the vulnerability. It is the vehicle. The fact that threat actors selected Deno over Node or Bun for this purpose tells you something about how the runtime landscape has matured: Deno's tooling, its single-binary distribution, and its built-in TypeScript support make it as convenient for adversaries as it is for application developers.
The three runtimes are now differentiated less by speed, all three are fast enough for nearly every use case, and more by the design tradeoffs they force teams to confront. Bun optimizes for developer experience and startup latency. Its recent adoption as the engine behind Electrobun, a new Electron alternative for TypeScript-powered desktop apps, shows how far the runtime has moved beyond its original framing as a faster Node drop-in. Electrobun promises a smaller application footprint and built-in update mechanisms, betting that Bun's TypeScript-native execution model is the right foundation for desktop software in an era where Electron's bundle size and memory usage have become punchlines.
Node.js, for its part, continues to optimize for stability and the platform it has already become. The type-stripping experiment is significant precisely because it is cautious. Node's maintainers know that the runtime's greatest asset is its install base: millions of production deployments, a package ecosystem that dwarfs both Bun's and Deno's, and a governance model that, for all its well-documented tensions, has kept the project viable through a decade of JavaScript churn. Adding native TypeScript support without breaking the npm ecosystem, without altering the module resolution algorithm, and without forcing a philosophical commitment to types-as-whitespace was the only move available. It was also the correct one.
But being correct is not the same as being exciting, and the excitement in the JavaScript community has shifted perceptibly toward Bun. The runtime's package manager, test runner, and bundler are all built in. There is no need for a separate tsconfig.json dance, no need to align versions across five toolchain components, no need to explain to a new hire why the project uses tsx in development but tsc in CI. Bun's bet is that the toolchain integration matters more than the runtime itself. For many teams, especially startups and small-to-medium projects, that bet has paid off.
The cost of this fragmentation is real, and it is borne disproportionately by the people who maintain shared libraries. A package author who wants to support all three runtimes must now contend with three different TypeScript execution models: Deno's full compilation, Bun's parse-time stripping, and Node's opt-in experimental stripping. Type declarations that work perfectly under tsc may behave differently, or not at all, when stripped at parse time. Enums, namespaces, and parameter properties are among the features that depend on compiler-emitted code, and their behavior varies across runtimes. The TypeScript team's decision to introduce a --stableTypeOrdering flag in TypeScript 6.0, explicitly designed to help developers match TypeScript 7.0 behavior ahead of the migration, is a quiet acknowledgment that the transition will not be seamless for everyone.
There is a human dimension to this fragmentation that benchmarks and compatibility matrices do not capture. When a team chooses Bun, it is also choosing a smaller community, fewer Stack Overflow answers, and a hiring pool that skews toward early adopters. When a team chooses Deno, it is choosing a security model that will generate friction, deliberate, designed friction, every time a script needs to touch the file system or make an outbound request. When a team stays on Node, it is choosing stability at the expense of the ergonomic improvements that Bun and Deno have made feel inevitable. None of these choices is wrong, but each comes with a maintenance burden that compounds over the life of a codebase.
The language itself is accelerating away from the runtime debate. TypeScript 7.0's Go port is not merely a performance upgrade; it is a statement about where the language's center of gravity now resides. A compiler written in Go can be embedded in editors, CI systems, and build tools in ways the JavaScript-based compiler could not. It can become infrastructure. The Go port also creates an interesting precedent: TypeScript is now serious enough to warrant a systems-language implementation, which makes it harder to dismiss as syntactic sugar over JavaScript. The language has outgrown its original framing.
What the runtime fragmentation makes clear is that TypeScript's success was never just about types. It was about tooling. The language won because tsc gave developers autocompletion, refactoring, and inline documentation that vanilla JavaScript could not. Now the runtimes are competing on the same axis: not who runs JavaScript fastest, but who provides the most coherent developer experience from the moment a project is initialized to the moment it ships. Bun bundles the toolchain. Deno bakes in security. Node integrates with everything. Each vision is coherent. None is complete.
The LeakNet ransomware story will fade from the news cycle, but the pattern it revealed will persist. When even cybercriminals are making considered runtime choices, evaluating distribution size, built-in TypeScript support, and single-binary deployment, the era of one-size-fits-all JavaScript is over. The question for the ecosystem is not which runtime wins. It is whether the runtimes can preserve enough interoperability that a package written for one still works, without ceremony, on the others. If they cannot, TypeScript's victory may prove hollow: a unified language running on fragmented ground.