TypeScript 运行时模型
TypeScript 代码最终要在 JavaScript 运行时中执行。2026 年的运行时格局已从”Node 一家独大”演变为 Node / Deno / Bun 三足鼎立——各有定位,各有取舍。
Python 只有 CPython 一个主流运行时,你基本不需要”选运行时”。而 TS 世界里运行时选择直接影响工具链和部署架构:选 Node 意味着 pnpm + Vite 生态,选 Bun 意味着原生 TS + 极速打包,选 Deno 意味着安全优先 + URL import。不确定选什么 → 先用 Node。
三大运行时概览
| 维度 | Node.js | Deno | Bun |
|---|---|---|---|
| 引擎 | V8 | V8 | JavaScriptCore (WebKit) |
| 实现语言 | C++ + JS | Rust | Zig |
| 包管理 | npm/pnpm(外部) | 内置(URL import) | 内置(极快) |
| TS 支持 | Node 23+ strip-types | ✅ 原生内置 | ✅ 原生内置 |
| 安全模型 | 无默认限制 | 默认沙箱(需显式授权) | 无默认限制 |
| 生态成熟度 | ★★★★★ | ★★ | ★★★ |
| 启动速度 | 中等 | 快 | 极快 |
| 适用场景 | 通用后端/全栈 | 安全敏感 + 轻量服务 | Greenfield 高性能项目 |
Node.js:无可争议的事实标准
2026 年现状
Node.js 仍是 TypeScript 后端开发的默认选择。生态成熟度、企业级支持、npm 海量包决定了它的统治地位。当前主流版本:
| 版本 | 状态 | 关键特性 |
|---|---|---|
| Node 20 LTS | 支持到 2026 | 长期稳定基线 |
| Node 22 LTS | 2025 末 → 2027 | 当前主力 LTS |
| Node 23 (Current) | 实验/领先功能 | 原生 TypeScript strip-types |
Node 23 的 TS 原生支持:转折点
Node 23.0 引入了 --experimental-strip-types,23.6 默认开启。这意味着:
# 无需 tsc/Babel/ts-node —— 直接运行
node server.ts工作原理:Node 在内置的 V8 管道中剥离 TypeScript 类型注解(只去掉,不检查),然后执行纯 JS 代码。这类似 Python 的解释器在 3.x 对类型注解的处理——解释器忽略它们。
适用边界:
| ✅ 适合直接运行 | ❌ 仍需要 tsc/打包 |
|---|---|
| CLI 工具 | 使用 enum/namespace 的代码 |
| 简单 HTTP 服务 | 需要 polyfill 的项目 |
| 脚本/自动化 | 需要 tree-shaking 的前端 bundle |
| 开发期快速迭代 | 浏览器兼容性要求 |
// Node 23 可直接运行
function greet(name: string): string {
return `Hello, ${name}`;
}
console.log(greet("World"));
// enum 在 strip-types 模式下被保留为 JS 代码
// 需要 tsc 降级处理
enum Color { Red, Green, Blue } // 生成 IIFE,不适合直接 stripnpm 包生态
Node 的最大护城河是 npm——200 万 + 包,覆盖几乎所有场景。Bun 和 Deno 虽然可以兼容 npm 包,但边缘 case(原生模块、node-gyp 编译)仍可能出错。
Python 对照:pip/PyPI 的地位类似 npm——都是各自的”默认包生态”。区别在于 npm 的包数量和精细化程度远超 PyPI,但碎片化也更严重(同一个功能有 17 个互相竞争的包)。
Bun:新项目的”尝鲜之选”
为什么 Bun 增长快
Bun 用 Zig 重写了整个运行时 + 包管理器 + 打包器 + 测试框架,追求”开箱即用的全栈体验”。
# 一条命令替代 node + pnpm + tsc + jest + webpack
bun run index.ts # 直接运行 TS
bun add express # 极快的包安装
bun build ./src # 原生打包
bun test # 原生测试运行器性能数据:Bun 的 HTTP 吞吐量在多项基准中领先 Node 数倍,包安装速度比 pnpm 更快(因为 Bun 的包管理器同样用 Zig 实现)。
Bun 的适用边界
| ✅ 优先 Bun | ❌ 保持 Node |
|---|---|
| 新建 Greenfield 项目 | 依赖大量原生 npm 包 |
| 追求极致冷启动速度 | 需要成熟的 APM/监控生态 |
| 一体化工具链偏好 | 企业已有 Node CI/CD 流程 |
| ElysiaJS 高性能后端 | 使用 node-gyp 编译的 C++ addon |
2026 年定位:Bun 更像”前瞻增量选择”而非默认主力。在 demo、CLI 工具、高性能微服务中已非常可靠,但在大型企业级后端中,Node 的生态厚度仍无法替代。
Deno:安全至上的”正确选择”
设计哲学差异
Deno 由 Node 原作者 Ryan Dahl 创建,核心卖点是默认安全 + 内置 TS + 标准库。
// Deno 的权限模型 —— 所有 I/O 操作需要显式授权
// deno run --allow-net --allow-read server.ts
// 从 URL 直接导入(零配置)
import { serve } from "https://deno.land/[email protected]/http/server.ts";
serve((req) => new Response("Hello, Deno!"));Deno 的优缺点:
| 优点 | 缺点 |
|---|---|
| 默认安全(无网络/文件权限 = 无法作恶) | 生态远小于 Node |
| 原生 TS 无需任何配置 | npm 兼容仍有边缘 case |
| 标准库内置(fmt、test、lint) | 企业采用率低 |
| 遵循 Web 标准 API | 不适合依赖大量 Node 专有 API 的项目 |
实际采用情况
2024–2026 年 Deno 虽然技术进步明显,但在生态增速上明显落后于 Node + Bun 组合。它在特定场景(安全敏感的微服务、边缘计算、CLI 工具)中是合理选择,但不太可能成为”下一代 Node”。
运行时选型决策树
graph TD START["新 TS 项目选运行时"] --> Q1{依赖大量 npm 包?} Q1 -->|是| Q2{有原生模块 node-gyp?} Q2 -->|是| NODE[Node.js] Q2 -->|否| Q3{团队规模?} Q3 -->|大团队/企业| NODE Q3 -->|小团队/个人| BOTH[Node 或 Bun 均可] Q1 -->|否| Q4{追求极致性能?} Q4 -->|是| Q5{需要一体化工具链?} Q5 -->|是| BUN[Bun] Q5 -->|否| Q6{需要默认安全?} Q4 -->|否| Q6 Q6 -->|是| DENO[Deno] Q6 -->|否| NODE
简化口诀:不知道怎么选 → Node;想尝鲜 → Bun;做安全工具/边缘服务 → 看看 Deno 是否适合。
与 Python 运行时的对比
| 维度 | TS/JS | Python |
|---|---|---|
| 运行时数量 | 多个竞争(Node/Deno/Bun) | 一个主导(CPython)+ 替代品 |
| 运行时选择 | 影响工具链和性能 | 默认 CPython |
| TS 原生支持 | Bun/Deno 原生;Node 23+ 逐步支持 | CPython 不原生支持”类型化 Python” |
| 启动速度 | Bun 极快;Node 中等 | 中等 |
| 并发模型 | 事件循环(单线程异步) | 多线程(GIL)/ asyncio 双轨 |
| 部署模型 | Serverless 优先 | 传统服务器优先 |
Python 中”运行时”基本 = CPython,不需要做选择;TS 中”运行时选择”直接影响项目架构。这既是自由,也是负担。
关联
- meta/并发模型 — 事件循环 vs 多线程哲学对比
- meta/编译与执行 — 跨语言执行模型
- TS 编译与执行 — tsc 与运行时如何配合
- TS 并发与事件模型 — 事件循环深入
- Python 并发与内存模型 — Python 对照
- TypeScript 专题 MOC
- Python: 并发与内存模型 — CPython 运行时对照