🔶 AI 编程已抹去静态类型语言所谓的优势
英文标题:🔶 AI Coding Has Erased the Supposed Advantage of Statically Typed Languages
文章认为,静态类型语言长期以来依赖编译器反馈、IDE 辅助和类型检查来降低人类编程错误,但这一前提正在因 AI 成为主要代码生产者而发生变化。作者指出,AI 能迅速修复普通语法和编译错误,真正昂贵的错误是需求误解、业务逻辑偏差、隐含假设和并发问题,而这些并不能由类型系统解决。对于 AI 而言,更多类型声明、泛型、接口和适配层意味着更多 token、更多一致性负担,以及更大的误解与出错表面积。文章主张,静态类型的价值仍应基于真实领域约束、工具链和模块边界来评估,但不应再被视为天然优于动态类型。
452 B
中文
多年来,静态类型语言的拥护者一直重复同一套论点:类型能够更早发现错误,编译器能提供更好的反馈,IDE 能给出更强的辅助,而大型代码库也更安全、更易维护。
这一论点建立在一个正迅速过时的假设上:编写代码的人是人类。
AI 不是人类。它不会因为 Python 感觉简单而偏爱 Python,也不会因为 Rust 显得严谨而欣赏 Rust。它没有偏好,没有情感依附,也没有编程语言身份认同。
对 AI 而言,不同语言最主要的区别在于:为了表达同一个想法,它需要生成多少代码,也就是多少 token。
语言越复杂,所需 token 就越多。所需 token 越多,模型犯错的机会也越多。
事情确实就这么简单。
AI 不需要类型系统来捕捉错误
当人类编写代码时,编译器反馈很重要。
人们会忘记函数签名,会混淆返回类型、忽略空值、漏掉字段,或者调用不存在的方法。类型检查器就像护栏一样,在程序运行前捕捉这些错误。
因此,很容易把同样的逻辑套用到 AI 身上:
静态类型语言能给 AI 更多反馈,因此 AI 能在其中生成更好的代码。
这在很大程度上是从人类编程时代继承而来的、类似货物崇拜式的推理。
你上一次看到一个能力足够强的编程模型卡在普通编译错误上,是什么时候?
缺少一个括号、基本类型写错,或调用了不存在的方法,已经不再是 AI 生成软件时的核心问题。这类错误偶尔会发生,但模型会读取编译器报错信息,几乎立刻修复它们。
AI 代价高昂的错误通常不是编译错误,而是误解。
模型实现了错误的业务规则,遗漏了边界情况,误读了数据的含义,破坏了未明示的并发假设。它可能生成一个类型完全正确、但逻辑完全错误的系统。类型检查器救不了你。
“AI 需要更多编译器反馈”这一说法听起来很技术化,但它往往只是重复旧论点,却没有正视现实:AI 几乎总能一次生成代码,大多数时候并不涉及编译器反馈。
类型也是成本
类型通常被描述为保护措施,却很少被视为成本。
然而,对于 AI 生成的代码来说,类型声明首先是必须生成、维护并保持一致的额外信息。
当类型编码了真实的领域约束时,它们是有价值的:
- 订单总额不能为负数。
- 已取消的交易不能再次结算。
- 未经认证的用户不能执行管理操作。
但许多类型信息并不表达此类约束。它们只是重复了从实现中已经显而易见的事实:
- 这个参数是字符串。
- 这个函数返回一个用户列表。
- 这个值可能不存在。
- 这个结构实现了这个接口。
在人类编程时代,这种重复有助于程序员理解陌生代码,也让 IDE 和编译器能够发现简单错误。
但 AI 模型本身已经是极其强大的模式识别器。它通常可以从名称、实现、调用位置、测试和周边上下文中推断出这些关系。
要求模型再次陈述所有信息,并不会自动提高正确性。它只会增加输出长度,并增加一项需要保持一致的义务。
如果一项约束无法消除有意义的业务错误,却需要额外增加数十个 token,那么它提供的可能只是仪式感,而非安全性。
编译已不再是稀缺能力
静态类型最常被宣传的好处是,它将错误前移到编译阶段。在 AI 辅助开发中,编译错误是成本最低的一类错误。
真正昂贵的错误是编译器看不见的那些:
- 需求被误解了。
- 测试编码了错误的假设。
- 数据模型没有反映真实业务。
- API 看上去合理,但破坏了兼容性。
- 并发代码通过了类型检查,但包含竞态条件。
- 授权逻辑能够编译,但允许未授权访问。
一个程序成功编译,只能证明它满足了其类型系统所表示的那一小部分规则。如今,这带来的价值并不大,因为任何前沿 AI 几乎都能一次满足这一狭窄要求。
既然 AI 生成的代码已经很少会卡在基础编译失败上,继续把编译器反馈描述为决定性优势,就像宣传自动驾驶汽车时把换挡指示器当成卖点。它或许并非毫无用处,但已经不再是重要问题。
更多类型意味着更多 token
对于 AI 来说,语言之间最有意义的差别之一,是表达同样行为需要多少 token。
在静态类型语言中,一个简单操作可能需要:
- 显式类型声明
- 泛型参数
- 接口或 trait
- 生命周期标注
- 错误类型转换
- 可选值包装器
- 数据传输对象
- 序列化标注
- 多层适配器代码
这些额外结构并非免费。更长的代码需要生成更多 token。更多符号必须在上下文中保持一致。修改会影响更多声明和更多文件。每增加一层抽象,模型就多一个可能误解程序员意图的地方。
AI 不会仅仅因为代码看起来更严谨就自动变得更正确。它只是需要保持一致的内容变得更多了。
更多 token 意味着更多出错机会。更多抽象层意味着更大的误解空间。更多类型机制意味着更多并不直接表达业务需求的代码。
另一方面,动态语言可能用少得多的代码行表达相同行为。例如,一项研究显示,作为动态语言的 Clojure 具有最高的 token 效率。
必须为 AI 时代重新计算语言成本
这并不意味着类型毫无价值。类型可以记录接口、定义模块边界、支持工具链,并编码真实的领域约束。
但现在必须诚实地评估这种成本。静态类型不应被视为天然更优。
从历史上看,类型系统通过增加代码和复杂性,换取降低人类认知负担并捕捉人类错误。
如今,越来越多的代码由 AI 生成、修改和解读。AI 没有同样的记忆局限,也很少会卡在语法或基础类型错误上。它的弱点在别处:模糊的需求、隐藏的假设、不断膨胀的上下文,以及不完美的语义理解。
旧有收益正在缩小,而旧有成本依然存在。
如今 token 已经成为可衡量的开支,这种成本比以往任何时候都更加显眼。
AI 不关心语言意识形态。它并未参与静态类型与动态类型之间的文化战争。它只是在生成 token。
如果两种语言都能解决同一个问题,但其中一种需要更多声明、更多样板代码、更多适配器和更多类型体操,那么这种复杂性并不会消失。它会变成更长的上下文、更高的生成成本,以及更大的错误表面积。
静态类型语言所谓的优势,建立在一个由人类作为代码主要生产者的世界之上。这个前提已经改变,结论也应随之改变。
English / 原文
For years, advocates of statically typed languages have made the same argument: types catch mistakes earlier, compilers provide better feedback, IDEs offer better assistance, and large codebases become safer to maintain.
That argument rests on an assumption that is rapidly becoming outdated: The person writing the code is human.
AI is not human. It does not prefer Python because Python feels simple. It does not admire Rust because Rust feels rigorous. It has no taste, no emotional attachment, and no programming-language identity.
To an AI, languages differ primarily in how much code, and therefore how many tokens, it must generate to express the same idea.
The more complicated the language, the more tokens it requires. The more tokens it requires, the more opportunities the model has to make a mistake.
It really is that simple.
AI Does Not Need a Type System to Catch Errors
Compiler feedback matters when humans write code.
People forget function signatures. They confuse return types, overlook null values, miss fields, and call methods that do not exist. A type checker acts as a guardrail, catching these mistakes before the program runs.
It is therefore tempting to apply the same logic to AI:
Statically typed languages give AI more feedback, so AI produces better code in them.
This is mostly cargo-cult reasoning inherited from human programming.
When was the last time you saw a capable coding model remain stuck on an ordinary compilation error?
A missing parenthesis, an incorrect primitive type, or a nonexistent method is no longer the central problem in AI-generated software. Such errors occasionally happen, but the model reads the compiler message and fixes them almost immediately.
AI's expensive mistakes are not usually compilation errors. They are misunderstandings.
The model implements the wrong business rule. It overlooks an edge case. It misinterprets the meaning of the data. It breaks an unstated concurrency assumption. It produces a system that is perfectly type-correct and logically wrong. A type checker cannot save you from that.
The claim that AI needs "more compiler feedback" sounds technical, but it often amounts to repeating an old argument without looking at the reality: AI almost always one-shot the code, and compiler feedbacks are not involved for the most part.
Types Are Cost Too
Types are usually described as protection. They are rarely counted as cost.
For AI-generated code, however, a type declaration is first and foremost additional information that must be generated, maintained, and kept consistent.
Types are valuable when they encode real domain constraints:
- An order total cannot be negative.
- A cancelled transaction cannot be settled again.
- An unauthenticated user cannot perform an administrative operation.
But much type information does not express constraints like these. It merely repeats facts that are already obvious from the implementation:
- This argument is a string.
- This function returns a list of users.
- This value might be absent.
- This structure implements this interface.
In the human-programming era, this repetition helped programmers understand unfamiliar code. It also allowed IDEs and compilers to catch simple mistakes.
But an AI model is already an extraordinarily capable pattern recognizer. It can often infer these relationships from names, implementations, call sites, tests, and surrounding context.
Requiring the model to state everything again does not automatically improve correctness. It increases output length and adds another consistency obligation.
If a constraint cannot eliminate a meaningful business error but requires dozens of additional tokens, it may be providing ceremony rather than safety.
Compilation Is No Longer the Scarce Capability
The most commonly advertised benefit of static typing is that it moves errors into the compilation stage. In AI-assisted development, compilation errors are among the cheapest errors possible.
The expensive errors are the ones the compiler cannot see:
- The requirement was misunderstood.
- The tests encode the wrong assumption.
- The data model does not reflect the real business.
- The API appears reasonable but breaks compatibility.
- The concurrent code type-checks but contains a race condition.
- The authorization logic compiles but permits unauthorized access.
A program compiling successfully proves only that it satisfies the small subset of rules represented by its type system. Nowadays, this does not buy much, because any frontier AI can almost always meet this narrow requirement in a single shot.
Since AI-generated code already spends very little time stuck on basic compilation failures, continuing to present compiler feedback as a decisive advantage is like advertising a self-driving car on the strength of its gear-change indicator. It may not be entirely useless, but it is simply no longer an important issue.
More Types Means More Tokens
For AI, one of the most meaningful differences between languages is how many tokens are required to express the same behavior.
In a static typed language, a simple operation may require:
- Explicit type declarations
- Generic parameters
- Interfaces or traits
- Lifetime annotations
- Error-type conversions
- Optional-value wrappers
- Data-transfer objects
- Serialization annotations
- Several layers of adapter code
Those additional structures are not free. Longer code requires more generated tokens. More symbols must remain consistent across the context. Changes touch more declarations and more files. Every additional abstraction creates another place where the model can misunderstand the programmer's intent.
AI does not automatically become more correct merely because the code looks more rigorous. It simply now has more things to keep consistent.
More tokens mean more opportunities for error. More abstraction layers mean more room for misunderstanding. More type machinery means more code that does not directly express the business requirement.
On the other hand, dynamic languages may express the same behavior in a lot less number of lines of code. For example, Clojure, a dynamic language, is shown to be the most token efficient in this study.
Language Costs Must Be Recalculated for the AI Era
This does not mean types have no value. Types can document interfaces, define module boundaries, support tooling, and encode genuine domain constraints.
But that cost must now be evaluated honestly. Static typing should not be treated as inherently superior.
Historically, type systems added code and complexity in exchange for reducing human cognitive load and catching human mistakes.
Now, an increasing share of code is generated, modified, and interpreted by AI. AI does not have the same memory limitations, and it rarely remains stuck on syntax or elementary type errors. Its weaknesses lie elsewhere: ambiguous requirements, hidden assumptions, sprawling context, and imperfect semantic understanding.
The old benefit is shrinking while the old cost remains.
And now that tokens are a measurable expense, that cost is more visible than ever.
AI does not care about language ideology. It is not participating in the culture war between static and dynamic typing. It is generating tokens.
If two languages can solve the same problem, but one requires more declarations, more boilerplate, more adapters, and more type gymnastics, that complexity does not disappear. It becomes a longer context, a higher generation cost, and a larger surface area for mistakes.
The supposed advantage of statically typed languages was built on a world in which humans were the primary producers of code. That premise has changed. The conclusion should change with it.