Elixir 1.20 最容易被误读的一句话,是 “now a gradually typed language”。很多人会顺手翻译成:Elixir 终于变成静态类型语言了。
别急。它还不是全面静态类型语言。当前阶段也还没有用户类型签名。真正的新东西更克制:普通 Elixir 代码不加类型注解,也能被做全程序类型推断和渐进式类型检查。
这一步对老项目很关键。它不是上来要求团队改写代码风格,而是先帮你找两类问题:死代码,以及 verified bugs。后者也别听大了,它不是所有 bug,只是类型违规,并且一旦执行就必然会在运行时报错的那类问题。
1.20 加了什么:先让现有项目跑起来
按官方发布信息看,Elixir 1.20 完成的是渐进式类型系统的第一个开发里程碑。
| 问题 | Elixir 1.20 的回答 | 对开发者的影响 |
|---|---|---|
| 要不要先写类型注解 | 不需要 | 老项目可以先跑检查,不必先大迁移 |
| 能查什么 | 死代码、verified bugs | 更早发现确定会炸的类型错误 |
| 类型路线是什么 | 渐进式类型,核心机制包括 dynamic() | 不把动态代码一刀切静态化 |
| 现在到哪一步 | 还没有用户类型签名 | 不能把它说成全面静态类型语言 |
| 下一步看什么 | typed struct、type signatures、性能约束 | 团队不应急着改规范,要先观察落地质量 |
时间线也不复杂。2022 年,Elixir 宣布走集合论类型方向。2023 年,相关论文发布,研发从研究转向开发。到 1.20,第一段开发目标落地。
官方还给了一个基准事实:在 IfT 类型收窄 benchmark 的 13 类测试里,Elixir 通过了 12 类。这个数字不能吹成行业第一。它更稳妥的含义是:Elixir 已经能从普通代码里恢复出较有用的类型信息。
对 Elixir / Erlang / BEAM 开发者来说,最现实的动作不是立刻“类型化改造”。更像是三件事:
- 在非关键分支升级到 1.20,先跑类型检查;
- 把 dead code 和 verified bugs 当成优先清理项;
- 暂时不要强制团队补类型签名,因为这部分能力还没推出。
这也是我更看重的地方。一个动态语言的类型系统,第一天最怕的不是能力不够强,而是让所有老项目一打开就红一片。
dynamic() 的重点:不是免检,而是可收窄
很多人看到渐进式类型,会自然想到 any()。在不少系统里,any() 像免检通行证。代码一旦落到这里,类型信息就被大片丢掉。
Elixir 1.20 强调的是 dynamic()。关键差别有两个词:compatibility 和 narrowing。
compatibility 的意思是,只要“供给类型”和“接受类型”还有交集,系统就不急着报错。它不把所有不确定都当错误。
narrowing 的意思是,类型范围会随着代码继续变窄。访问字段、模式匹配、分支判断,都可能让系统恢复更多信息。
举个简化例子。一个值可能是 integer() 或 binary()。如果后续操作还能和其中一部分类型兼容,Elixir 不会立刻判死刑。
但如果你把一个只可能是整数或字符串的值传给 Map.fetch!,问题就明确了。map 和 integer / binary 不相交。这类冲突就可能被报出来。
这就是低误报的工程价值。
动态语言社区真正怕的不是类型理论。怕的是工具把不确定当错误,把风格差异当错误,把迁移成本扔给业务团队。结果就是 CI 变红,大家关检查,类型系统成了摆设。
Elixir 这条路更像先递一把小刀,只切确定的肉。它不急着证明自己管得宽,而是先证明自己报得准。
成败不在“有没有类型”,在团队信不信它
动态语言补类型,历史上一直不是纯技术题。Python、JavaScript、Ruby 都走过类似路。类型系统要进入旧代码库,第一仗打的是误报率、迁移成本和团队耐心。
“天下熙熙,皆为利来。”放到工程工具里也成立。开发者愿意接受新约束,前提是它先给收益,而不是先收税。
Elixir 1.20 这次顺序摆得比较对。先不逼你写签名。先不要求你重塑代码风格。先帮你抓一批确定会炸的错误。
这比“宣布进入类型时代”更实在。
我不太买账那种上来就教育社区的语言设计。工具一旦像审判官,开发者就会绕开它。Elixir 现在更像一个谨慎的同事:它不说你写得不够现代,只说这里如果跑到,一定会炸。
这句话分量够了。
限制也要说清。1.20 不是终点。类型签名还没推出。递归类型、参数化类型、map 键值遍历作为 enumerable 的效率问题,仍然是现实约束。官方也提到,只有性能和基础问题满足要求后,才会继续探索 typed struct 和 type signatures。
所以接下来最该看的不是口号,而是三个变量:
- 类型检查在真实老项目里的误报率;
- typed struct 和 type signatures 推出时的迁移成本;
- 递归类型、参数化类型、map 遍历相关性能能不能压住。
如果这三项走稳,Elixir 的渐进类型才算真正进入可推广阶段。如果误报上升,或者签名迁移太重,团队还是会回到老办法:能关就关,能绕就绕。
这也是动态语言补类型的老问题。理论漂亮只是入场券。工程上能不能赢,靠的是克制、准确和信任。
