Skip to main content

sim-ts

你的观察很敏锐!Python 的类型注解(Type Hints)和 TypeScript 的类型语法确实非常相似,这是因为它们都受到了现代静态类型语言(如 Java、C#、OCaml、Haskell)的影响,并且都致力于在动态语言的基础上增加可选的静态类型检查

相似点一览

特性PythonTypeScript
变量类型注解name: strname: string
函数参数与返回值def f(x: int) -> str:function f(x: number): string
可选/联合类型str | NoneOptional[str]string | nullstring | undefined
泛型List[T]Dict[K, V]Array<T>Map<K, V>
类型别名UserId = inttype UserId = number
接口/协议Protocol(typing 模块)interface
字面量类型Literal["foo"]"foo"
类型守卫isinstance(x, str)typeof x === "string"

为什么这么像?

  1. 共同的语法源头
    两者都采用 变量: 类型 这种后缀类型注解的方式,和 C/C++/Java 的 类型 变量 前缀风格不同。这种后缀风格其实在 Pascal、Ada、Rust、Scala 中很常见。Python 从 2006 年的 PEP 3107 就开始支持函数注解(当时没固定语义),后来 2014 年的 PEP 484(类型提示)正式确立了语法;TypeScript 2012 年诞生时也选择了这种风格。

  2. 目标一致:动态语言的静态检查
    Python 和 TypeScript 都是在动态类型基础上提供可选的静态类型系统,因此都需要:

    • 不破坏运行时行为(Python 的类型注解不强制,TS 的类型会在编译后擦除)
    • 语法尽量简洁、直观,不喧宾夺主
    • 支持渐进式迁移(旧代码可以不写类型)
  3. 互相借鉴
    虽然两者独立发展,但开发者社区经常互相参考。Python 3.10 引入的 | 联合类型int | None)就和 TypeScript 的 | 非常像。TypeScript 的 as 类型断言也在 Python 的 typing.cast() 中有对应。

核心区别(不只是语法)

方面PythonTypeScript
类型检查时机需要第三方工具(mypy、pyright)在开发时或 CI 阶段检查集成在编译器(tsc)中,编译时检查
运行时行为类型注解完全保留,可通过 __annotations__ 访问,但不会自动检查类型在编译后完全擦除,不产生运行时开销
泛型实现基于类型擦除(类似 Java),但使用 TypeVar基于结构类型系统(structural typing),也有泛型擦除
空值处理None 默认可以赋给任何类型,除非开启 strictOptional 或使用 Optional默认严格,string 不能赋 null/undefined,除非配置 strictNullChecks

简单示例对比

Python:

def greet(name: str | None) -> str:
if name is None:
return "Hello, stranger"
return f"Hello, {name}"

TypeScript:

function greet(name: string | null): string {
if (name === null) {
return "Hello, stranger";
}
return `Hello, ${name}`;
}

小结

你的感觉完全正确 —— 它们很像,因为:

  • 都选择了后缀类型注解语法(变量: 类型
  • 都支持联合类型、泛型、类型别名等现代类型特性
  • 都致力于在动态语言中提供渐进式的静态类型检查体验

虽然语法相似,但背后的类型系统哲学略有不同(Python 是名义类型 + 可选鸭子类型,TypeScript 是结构化类型),不过日常写起来的感觉确实十分接近。如果你同时写 Python 和 TypeScript,你会发现类型注解几乎可以“无缝切换” 😄