Skip to main content

Introducing T-Ruby

We're excited to introduce T-Ruby, a TypeScript-style static type system for Ruby.

T-Ruby brings the familiar TypeScript development experience to Ruby developers, allowing you to add type annotations directly in your code and catch type errors before runtime.

Key Features​

  • TypeScript-style syntax: Familiar type annotation syntax for TypeScript developers
  • Gradual typing: Add types incrementally to your existing Ruby codebase
  • RBS generation: Automatically generate .rbs signature files
  • Zero runtime overhead: Types are stripped at compile time

Getting Started​

Install T-Ruby and start adding types to your Ruby code:

gem install t-ruby

Create your first .trb file:

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

Compile to Ruby:

trc greet.trb

Check out our documentation to learn more!

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, 42 → Integer
  • Method call tracking: str.upcase → String
  • 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!