Skip to main content

Type Inference: Write Less, Type More

T-Ruby now automatically infers return types from your code. No more explicit annotations for obvious types!

What's New

Previously, you had to write:

def greet(name: String): String
"Hello, #{name}!"
end

Now, the return type is optional:

def greet(name: String)
"Hello, #{name}!"
end

T-Ruby infers that greet returns String and generates the correct RBS:

def greet: (name: String) -> String

How It Works

The new type inference engine analyzes method bodies to determine return types:

  • Literal inference: "hello"String, 42Integer
  • Method call tracking: str.upcaseString
  • Implicit returns: Ruby's last expression becomes the return type
  • Conditional handling: Union types from if/else branches

Examples

Simple Methods

class Calculator
def double(n: Integer)
n * 2
end

def is_positive?(n: Integer)
n > 0
end
end

Generated RBS:

class Calculator
def double: (n: Integer) -> Integer
def is_positive?: (n: Integer) -> bool
end

Instance Variables

class User
def initialize(name: String)
@name = name
end

def greeting
"Hello, #{@name}!"
end
end

Generated RBS:

class User
@name: String

def initialize: (name: String) -> void
def greeting: () -> String
end

Technical Details

The inference system is inspired by TypeScript's approach:

  • BodyParser: Parses T-Ruby method bodies into IR nodes
  • TypeEnv: Manages scope chains for variable type tracking
  • ASTTypeInferrer: Traverses IR with lazy evaluation and caching

For a deep dive into the implementation, check out our technical blog post.

Try It Now

Update to the latest T-Ruby and enjoy automatic type inference:

gem update t-ruby

Your existing code will work as before - explicit types still take precedence. The inference only kicks in when return types are omitted.

Feedback

We'd love to hear your experience with type inference. Found an edge case? Have suggestions? Open an issue on GitHub.

Happy typing!