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, 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!