TypeProf 入门:自动生成 RBS 类型签名的官方工具
TypeProf 是 Ruby 官方类型推导引擎,分析源码自动生成 RBS 签名,随 Ruby 3.0+ 自带。本文讲解其推导原理、使用方法、能力边界与"TypeProf 草稿 + 人工精修 + Steep 检查"的完整工作流。
TypeProf 通过抽象解释分析 Ruby 代码中值的流动,自动推导出方法和类的类型,输出 RBS 签名草稿。它让老项目零成本获得类型覆盖的起点——生成草稿、人工收紧、交给 Steep 做持续检查,是 RBS 体系落地的标准路径。
TypeProf 解决什么痛点
给老项目引入 RBS 最大的障碍是"几万行代码的手写签名"。TypeProf 把这个成本降到接近零:一条命令扫描代码,产出覆盖全部方法的 RBS 草稿。草稿不完美(大量 untyped),但它把"从零开始"变成"从 60 分开始"——人工只需收紧关键部分。
基本用法
TypeProf 随 Ruby 3.0+ 自带,无需安装:
typeprof lib/user.rb # 分析单文件,输出 RBS 到终端
typeprof lib/user.rb -o sig/user.rbs # 写入文件
typeprof lib/ # 分析目录
输入普通 Ruby 源码,输出 RBS:
class User
def initialize(name)
@name = name
end
def adult?(age)
age >= 18
end
end
class User
def initialize: (untyped name) -> untyped
def adult?: (Integer age) -> bool
end
推导原理:抽象解释
TypeProf 不执行代码,而是"在类型层面执行":跟踪每个表达式可能产生的类型集合,流过方法调用、分支与赋值。字面量 18 推导出 Integer、比较运算推导出 bool——这就是上面 adult? 被精确推导的原因。它没有注解也能工作,这正是它与"检查签名"类工具(Steep)的本质区别:一个生成类型信息,一个验证类型信息。
能力边界:知道它推不出什么
TypeProf 的诚实之处在于局限性明确:
- 动态特性是盲区:
define_method、method_missing、send动态调用的方法无法推导,输出为 untyped 或缺失; - 复杂的元编程(Rails 的 has_many 生成的方法群)超出静态分析能力,需要 rbs_rails 等专门生成器补齐;
- ambiguous 的写法(一个变量装多种类型)会推导出宽类型或 untyped;
- 分析耗时代码规模增长明显,巨型项目需要分批处理。
实践推论:TypeProf 产出的是"初稿"而非"定稿"——动态部分靠人工或领域生成器补,含糊部分人工收紧。
完整工作流:从草稿到 CI 守卫
- 生成:
typeprof对核心目录批量生成 .rbs 草稿,提交 sig/ 目录; - 精修:核心领域模型手工收紧类型(untyped → 具体类型),公开 API 精确描述;
- 检查:Steep 加载签名执行
steep check,类型错误在 CI 拦截; - 迭代:新代码先写实现,
typeprof补草稿再人工收紧,签名与实现同步演进。
这套流程让类型覆盖随时间单调提升,且每一步都有工具兜底。
TypeProf 在类型生态中的位置
Ruby 类型工具链分工:TypeProf(推导生成)→ RBS(签名格式)→ Steep(静态检查)→ rbs collection(三方 gem 签名库)。Sorbet 阵营则自成一体(sig 注解 + srb tc)。TypeProf 是 RBS 路线的"冷启动引擎"——没有它,老项目接入 RBS 的成本会让大多数团队望而却步。
常见问题(FAQ)
Q:TypeProf 能替代手写签名吗?
不能完全替代。它对"直来直去"的代码推导良好,对动态代码无能为力;公共 API 的精确契约(联合类型、泛型、块签名)仍需人工编写。正确定位是"草稿生成器 + 覆盖率加速器"。
Q:分析结果里 untyped 太多怎么办?
两个方向改善:给 TypeProf 提供"锚点"——在关键方法上手写少量 RBS,推导会顺着这些已知类型扩散得更准;重构歧义代码(如一个变量装不同类型),代码本身清晰了推导自然精确。
Q:TypeProf 和 Sorbet 的推导有什么区别?
Sorbet 的推导服务于其内嵌注解体系(检查 sig 之外代码的类型一致性),产物不导出为独立签名文件;TypeProf 的产物是标准 RBS,可被整个 RBS 工具链消费。选哪个阵营看项目整体类型策略,详见本系列《Sorbet 和 RBS 怎么选》。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。