
January 28, 2026
TypeProf is an official type inference tool for Ruby that has gained attention as part of the ecosystem surrounding RBS, Steep, and Sorbet. Despite this visibility, it is frequently misunderstood and often perceived as “not working” by first-time users. This article analyzes TypeProf from a design and usability perspective, based on its presentation by Yusuke Endoh at RubyKaigi 2025, and on hands-on experimentation. We argue that most user frustration stems not from technical failure, but from mismatched expectations regarding what TypeProf is designed to do.
1. Introduction: When Silence Feels Like Failure
In statically typed ecosystems, tooling feedback is often immediate and explicit: errors are underlined, diagnostics are surfaced, and contracts are enforced. When Ruby developers approach TypeProf with a similar mental model, the result is often confusion:
“I installed TypeProf, but it doesn’t report any errors.”
This reaction is understandable—but misleading. TypeProf’s apparent silence is not accidental. It is the consequence of deliberate design choices that prioritize scalability, soundness, and low false-positive rates over strictness. Understanding these choices is essential to using the tool effectively.

2. What TypeProf Is (by Design)
TypeProf is fundamentally a type inference engine for Ruby. Its primary goals are:
- To infer method signatures from existing Ruby code
- To improve editor support (navigation, completion, symbol resolution)
- To generate RBS definitions as a byproduct of analysis
Crucially, TypeProf aims to achieve these goals with minimal or no type annotations. This places it closer to research-oriented inference systems than to enforcement-oriented type checkers.
As emphasized in Endoh’s RubyKaigi 2025 talk, TypeProf is optimized for understanding code, not judging it.
3. The Conservative Core: Why TypeProf Rarely Complains
A defining characteristic of TypeProf is its conservative inference strategy. When faced with uncertainty, TypeProf prefers to infer untyped rather than emit a potentially incorrect diagnostic.
Consider the following Ruby code:
def bar(x) x + 1end
From a human perspective, this method “expects” a numeric value. From TypeProf’s perspective, however, x may be any object that implements #+. Since Ruby allows such dynamism, the most sound inference is:
def bar: (untyped) -> untyped
Once untyped enters the analysis, many potential inconsistencies disappear. This is not a limitation of implementation, but a logical consequence of Ruby’s semantics combined with TypeProf’s soundness guarantees.
4. What TypeProf Explicitly Does Not Do
To avoid further confusion, it is important to state clearly what TypeProf is not intended to do:
- It does not detect runtime errors (e.g. division by zero)
- It does not enforce contracts
- It does not behave like a linter
- It does not aim to be a “TypeScript for Ruby”
Errors such as:
"hello" + 1
are runtime type errors in Ruby, but they do not necessarily represent static type contradictions. As such, TypeProf will often remain silent. This behavior is consistent, intentional, and documented.
5. The Real Value Proposition: Inference as Infrastructure
TypeProf’s strongest use case emerges when it is treated as infrastructure, not as a final authority. Its ability to infer large portions of a codebase’s type surface makes it particularly valuable when combined with stricter tools.
A common and effective workflow is:
- Use TypeProf to infer RBS from existing code
- Refine and stabilize the generated RBS
- Apply Steep or Sorbet to enforce correctness
In this sense, TypeProf acts as an on-ramp to typed Ruby, dramatically lowering the cost of adoption.
6. Lessons from Constant Resolution
One of the most technically interesting sections of the RubyKaigi 2025 presentation concerns Ruby’s constant resolution rules. These rules are complex, context-dependent, and sensitive to changes in inheritance and module inclusion.
TypeProf originally attempted to re-analyze constant resolution aggressively, which led to subtle infinite-loop bugs. The eventual solution was not increased sophistication, but strategic simplification: abandoning certain inheritance-based constant lookups to preserve termination and predictability.
This episode illustrates a broader theme: TypeProf consistently trades completeness for robustness.
7. Implications for Tooling Expectations
Understanding TypeProf requires a shift in mindset:
- Silence does not imply inactivity
- Lack of diagnostics does not imply lack of analysis
- Precision is intentionally sacrificed to avoid false confidence
Once these principles are internalized, TypeProf becomes easier to evaluate—and easier to appreciate.

8. Conclusion
TypeProf is best understood not as a type checker, but as a type inference substrate for Ruby. Its design prioritizes scalability, soundness, and editor support over strict enforcement. When used with appropriate expectations—and especially when combined with tools like Steep or Sorbet—it provides substantial value.
The frustration many users experience is real, but it is rooted in a category error: expecting TypeProf to solve a problem it was never designed to address. Reframed correctly, TypeProf is not silent—it is simply careful.
