Back to skills
extension
Category: Development & EngineeringNo API key required

rbs-files

Write standalone .rbs signature files to describe Ruby code. Use when creating type definitions for gems, libraries, or existing codebases without modifying Ruby source.

personAuthor: jakexiaohubgithub

Standalone RBS Files

Write type signatures in separate .rbs files in a sig/ directory. Ruby source files remain unchanged.

Quick Start

# sig/person.rbs
class Person
  attr_reader name: String
  attr_reader age: Integer?

  def initialize: (String name, ?Integer? age) -> void
  def greet: () -> String
end

File Structure

project/
├── lib/
│   └── person.rb          # Ruby implementation
├── sig/
│   ├── person.rbs         # Type signatures
│   ├── _private/          # Hidden from library users
│   │   └── internal.rbs
│   └── manifest.yaml      # Stdlib dependencies
└── Steepfile

Class and Module Declarations

# Basic class
class User
end

# With superclass
class Admin < User
end

# With type parameters
class Container[T]
end

# Module
module Logging
end

# Module with self-type constraint
module Enumerable[Elem] : _Each[Elem]
end

Method Definitions

class Calculator
  # Instance method
  def add: (Integer, Integer) -> Integer

  # Singleton (class) method
  def self.create: () -> Calculator

  # Module function (both singleton and private instance)
  def self?.sqrt: (Numeric) -> Float

  # Visibility
  private def internal: () -> void
end

Method Type Syntax

# Required positional
def foo: (String, Integer) -> void

# Optional positional (? prefix)
def foo: (String, ?Integer) -> void

# Rest positional
def foo: (*String) -> void

# Required keyword
def foo: (name: String) -> void

# Optional keyword
def foo: (?name: String) -> void

# Keyword rest
def foo: (**String) -> void

# Block (required)
def foo: () { (String) -> Integer } -> void

# Block (optional, ? before brace)
def foo: () ?{ (String) -> Integer } -> void

# Complex signature
def foo: (
  String,                    # Required positional
  ?Integer,                  # Optional positional
  *Symbol,                   # Rest positional
  name: String,              # Required keyword
  ?age: Integer,             # Optional keyword
  **untyped                  # Keyword rest
) { (String) -> void } -> Array[String]

Method Overloading

class Array[Elem]
  # Multiple signatures with |
  def *: (String) -> String
       | (Integer) -> Array[Elem]

  # Extending existing method with ...
  def fetch: (Integer) -> Elem
           | ...
end

Attributes

class User
  # Reader (generates getter + @name ivar)
  attr_reader name: String

  # Writer (generates setter + @email ivar)
  attr_writer email: String

  # Accessor (generates both)
  attr_accessor age: Integer

  # Custom ivar name
  attr_reader display_name (@raw_name): String

  # No ivar (computed property)
  attr_reader full_name (): String

  # Singleton attribute
  attr_reader self.instance: User
end

Instance and Class Variables

class Counter
  @count: Integer                    # Instance variable
  self.@instances: Array[Counter]    # Class instance variable
  @@total: Integer                   # Class variable
end

Constants

class Config
  VERSION: String
  MAX_SIZE: Integer
  VALID_STATES: Array[Symbol]
end

# Global variable
$LOAD_PATH: Array[String]

Interfaces

Define duck types that classes can implement:

interface _Readable
  def read: (?Integer) -> String?
  def eof?: () -> bool
end

interface _Writable
  def write: (String) -> Integer
end

class MyIO
  include _Readable
  include _Writable
end

Type Aliases

# Simple alias
type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]

# Generic alias
type result[T] = [true, T] | [false, String]

# Scoped to class
class MyApp
  type callback = ^(String) -> void
end

Generics

# Basic generic class
class Box[T]
  def initialize: (T) -> void
  def get: () -> T
end

# Variance annotations
class ReadOnly[out T]        # Covariant
  def get: () -> T
end

class WriteOnly[in T]        # Contravariant
  def set: (T) -> void
end

# Unchecked variance (for mutable collections)
class Array[unchecked out T]
end

# Upper bound
class Sorter[T < Comparable]
  def sort: (Array[T]) -> Array[T]
end

# Default type
class Cache[T = String]
end

# Method-level generics
class Util
  def self.identity: [T] (T) -> T
  def self.map: [T, U] (Array[T]) { (T) -> U } -> Array[U]
end

Mixins

class User
  include Comparable
  include Enumerable[String]
  extend ClassMethods
  prepend Instrumentation
end

Use Directive

Import types to avoid fully-qualified names:

use RBS::TypeName
use RBS::AST::*

class MyParser
  def parse: (TypeName) -> untyped
end

manifest.yaml

Declare stdlib dependencies for gems:

# sig/manifest.yaml
dependencies:
  - name: json
  - name: pathname
  - name: set

Validate Signatures

# Check RBS syntax and consistency
bundle exec rbs validate

# Test signatures against runtime
RBS_TEST_TARGET='MyApp::*' bundle exec ruby -r rbs/test/setup test/my_test.rb