TypeScript 和 Python 都是高级语言,都有垃圾回收、一等函数和庞大的包生态。主要区别在于类型:TypeScript 的类型由编译器在程序运行之前检查,而 Python 的类型提示是可选的注解,解释器会忽略它们。两者还运行在不同的引擎上,主导着不同类型的软件:TypeScript 主导 Web,Python 主导数据处理和脚本。
下面是一个用 TypeScript 写的小程序。点击“运行”:
输出:
162.25
[ 'Ada', 'Grace', 'Linus' ]
用 Python 写同一个程序,并加上类型提示:
from dataclasses import dataclass
@dataclass
class Order:
customer: str
amount: float
paid: bool
def total_paid(orders: list[Order]) -> float:
return sum(o.amount for o in orders if o.paid)
orders = [
Order("Ada", 120.0, True),
Order("Grace", 80.5, False),
Order("Linus", 42.25, True),
]
by_amount = [o.customer for o in sorted(orders, key=lambda o: o.amount, reverse=True)]
print(total_paid(orders))
print(by_amount)
162.25
['Ada', 'Grace', 'Linus']
两者的结构很接近:一个描述记录的类型、一个带类型参数的函数、一个值的列表。看得见的区别在于语法(花括号和分号对比缩进)、interface 对比 @dataclass,以及箭头函数配合 filter/reduce 对比生成器表达式。
TypeScript 与 Python 一览
| TypeScript | Python | |
|---|---|---|
| 类型 | 静态,在编译期检查;运行时类型被擦除 | 动态;类型提示可选,运行时不强制执行 |
| 类型检查器 | tsc,语言自带 | 独立工具:mypy、pyright 等 |
| 运行环境 | JavaScript 引擎:浏览器、Node.js、Deno、Bun | CPython(标准解释器)、PyPy 等 |
| 执行方式 | 编译成 JavaScript,再由引擎即时编译(JIT) | 在 CPython 中解释执行字节码 |
| 代码块 | 花括号 { } | 缩进 |
| 数字 | number(64 位浮点数)和 bigint | int(任意大小)和 float |
| 并发 | 每个事件循环一个线程,async/await;并行任务用 worker | asyncio、线程、多进程 |
| 包管理器 | npm、pnpm、Yarn、Bun | pip、uv、Poetry |
| 最擅长的领域 | Web 前端、Node.js 后端、全栈应用 | 数据科学、机器学习、脚本、自动化、后端 |
语法对照
如果你熟悉 Python 的类型提示,大多数 TypeScript 注解都有直接对应的写法:
| Python | TypeScript |
|---|---|
count: int = 0 | let count: number = 0; |
def add(a: int, b: int) -> int: | function add(a: number, b: number): number { |
lambda x: x * 2 | (x) => x * 2 |
list[str] | string[] |
dict[str, int] | Record<string, number> 或 Map<string, number> |
tuple[int, str] | [number, string] |
str | None | string | null 或 string | undefined |
Literal["asc", "desc"] | "asc" | "desc" |
Callable[[int], str] | (n: number) => string |
TypedDict | interface 或 type |
@dataclass | class,纯数据可用 interface |
Any | any |
None、True、False | null(或 undefined)、true、false |
and、or、not | &&、||、! |
f"Hello {name}" | `Hello ${name}` |
静态类型与类型提示
两种语言都能写出同样的注解,a: number 或 a: int。但接下来发生的事情不同。
在 TypeScript 中,编译器会在任何代码运行之前检查每一次调用。参数类型不对,构建就会停止:
index.ts(7,17): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
在 Python 中,类型提示只是元数据。解释器照常执行调用,并返回一个字符串:
def add(a: int, b: int) -> int:
return a + b
print(add(2, 3)) # 5
print(add("2", "3")) # 23, the hints are not enforced
检查是用 mypy 这类工具完成的一个独立步骤:
$ mypy hints.py
hints.py:6: error: Argument 1 to "add" has incompatible type "str"; expected "int" [arg-type]
hints.py:6: error: Argument 2 to "add" has incompatible type "str"; expected "int" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
所以 Python 的类型系统在设计上是渐进式的:没有注解的代码根本不会被检查,你只在有帮助的地方添加类型提示。TypeScript 也可以很宽松(any 会关闭对某个值的检查),但在默认开启的 strict 模式下,没有注解的参数会报错,而不是直接放行。
两者有一个共同点:都不会在程序运行时检查类型。TypeScript 会擦除类型,Python 会忽略类型提示。运行时传入的数据,例如来自 API 的 JSON,在两种语言中都需要校验(TypeScript 的 Zod 和 Python 的 Pydantic 这类库可以根据 schema 完成校验)。
数字的行为不同
TypeScript 沿用 JavaScript 的数字:number 是 64 位浮点数,整数和小数都用它表示,bigint 则是专门用于大整数的独立类型。Python 的 int 会自动增长到任意大小。
输出:
0.30000000000000004
9007199254740992
3.5 3
1267650600228229401496703205376n
对于 2**53 + 1,Python 输出 9007199254740993,因为它的整数在任何大小下都是精确的;Python 还有专门的整除运算符 7 // 2,结果是 3。TypeScript 中没有 int 类型;整数只是恰好没有小数部分的 number。
运行时与性能
TypeScript 以 JavaScript 的形式运行。V8(用于 Chrome 和 Node.js)、JavaScriptCore(用于 Safari 和 Bun)和 SpiderMonkey(用于 Firefox)会在运行时把热点代码编译成机器码,所以 TypeScript 中的密集循环通常比 CPython 中同样的循环快得多,因为 CPython 执行的是字节码。
对很多程序来说,这个差距并没有听起来那么重要:
- Python 的数值计算和机器学习库(NumPy、pandas、PyTorch)在编译好的 C、C++ 或 CUDA 代码中完成繁重的工作,所以调用它们的 Python 程序,其内层循环并不是在 Python 中运行的。
- 无论用哪种语言写的 Web 服务器,大部分时间都在等待数据库和网络。
两种语言的大部分代码都运行在一个主线程上。Node.js 上的 TypeScript 用事件循环和 async/await 处理并发,用工作线程处理并行的 CPU 任务。Python 有 asyncio 提供同样风格的并发,此外还有线程和进程。
生态与用途
TypeScript 是以下领域的默认选择:
- Web 前端:React、Angular、Vue 和 Svelte 都支持它,它会编译成浏览器运行的 JavaScript。
- Node.js、Deno 和 Bun 上的服务器代码:用 Express、Fastify、NestJS 或 Hono 编写的 API。
- 服务器和浏览器共享类型定义的全栈应用,例如 Next.js 项目。
- 开发工具、命令行工具,以及用 Electron 开发的桌面应用。
Python 是以下领域的默认选择:
- 数据分析和可视化(pandas、NumPy、Matplotlib、Jupyter notebook)。
- 机器学习和 AI(PyTorch、scikit-learn,以及大部分模型训练代码)。
- 脚本和自动化:文件处理、系统管理、胶水代码。
- 用 Django、Flask 或 FastAPI 开发的 Web 后端。
- 科学计算和教学。
Web 后端开发是两者重叠最多的地方。团队通常根据技术栈的其余部分来选择:要和 TypeScript 前端共享代码就选 TypeScript,要和数据及机器学习代码放在一起就选 Python。
应该学哪一个?
- 做 Web 开发? 先学 JavaScript,再学 TypeScript。浏览器中运行的一切最终都是 JavaScript,而大多数专业的前端代码都是用 TypeScript 写的。
- 做数据、AI 或自动化? 学 Python。它在这些领域的库,在 JavaScript 世界里没有真正的替代品。
- 第一门语言,还没有明确目标? Python 需要学的语法更少,就能写出有用的程序。TypeScript 在 JavaScript 之上加了一套类型系统,一开始需要多学一些,但随着程序变大会越来越有回报。
很多开发者两者都用:Python 处理数据和脚本,TypeScript 编写产品的 Web 代码。如果你已经熟悉 Python 的类型提示,TypeScript 的注解会让你觉得眼熟;新的地方在于编译器默认强制执行它们,而底层的运行时是 JavaScript。
常见问题
TypeScript 比 Python 好吗?
总体上谁也不比谁好,它们各自在不同领域领先。TypeScript 是 Web 前端的标准选择,在 Node.js 服务器中也很常见,类型检查是日常开发流程的一部分。Python 在数据科学、机器学习、脚本和自动化领域领先,它的类型提示可以用 mypy 或 pyright 等工具检查。
TypeScript 比 Python 快吗?
对于用语言本身编写的 CPU 密集型代码,通常是的:TypeScript 编译成 JavaScript,V8 这样的引擎会在运行时把它编译成机器码,而 Python 的标准解释器 CPython 执行的是字节码。主要时间花在 C 语言编写的库(NumPy、pandas、PyTorch)中的 Python 程序不受此限制;对于受网络限制的服务器,差别往往也很小。
Python 有像 TypeScript 那样的静态类型吗?
Python 有可选的类型提示(def add(a: int, b: int) -> int),但解释器不会强制执行它们:add("2", "3") 能运行并返回 "23"。需要用 mypy 或 pyright 这样的独立检查工具来报告类型不匹配。在 TypeScript 中,检查是编译器的主要工作,项目通常配置为存在类型错误的代码无法构建。
应该先学 TypeScript 还是 Python?
根据你想做的东西来选。要做网站和 Web 应用,先学 JavaScript,再学 TypeScript,因为浏览器只运行 JavaScript。要做数据分析、机器学习、自动化,或者想找一门语法很少的入门语言,就从 Python 开始。无论选哪个,核心概念(变量、函数、循环、对象)都可以迁移。