Skip to content

Add RBS Type Signatures to Improve Developer Experience #1929

@justin808

Description

@justin808

Add RBS Type Signatures to Improve Developer Experience

Problem

Currently, both shakapacker and react_on_rails lack static type information for their Ruby APIs. This means:

  • IDEs cannot provide accurate autocomplete or type hints
  • Type errors are only caught at runtime, not during development
  • API documentation is limited to comments and external docs
  • Refactoring is riskier without type checking

Proposal

Adopt RBS (Ruby Signature) files to provide static type information for our public APIs, following the pattern successfully used in the package_json gem.

What is RBS?

RBS is Ruby's official type annotation system that:

  • Lives in separate .rbs files (usually sig/ directory)
  • Keeps Ruby code clean without inline type annotations
  • Provides machine-readable type information for tools
  • Enables static type checking with tools like Steep or TypeProf
  • Powers IDE features like autocomplete and error detection

Benefits

For Users

  1. Better IDE Support - Accurate autocomplete and inline type hints
  2. Catch Errors Earlier - Type checker catches issues before runtime
  3. Self-Documenting - Types are explicit and machine-readable
  4. Safer Refactoring - Type checker catches breaking changes

For Maintainers

  1. Clearer Interfaces - Types document expected inputs/outputs
  2. Reduce Bugs - Catch type mismatches during development
  3. Easier Onboarding - New contributors understand APIs faster
  4. Consistent with Ecosystem - Many gems adopting RBS

Proposed Phased Rollout

Phase 1: Core Public APIs (Week 1-2)

  • react_on_rails:

    • ReactOnRails.configure and configuration classes
    • ReactOnRails::Helper module (react_component, etc.)
    • Component registration methods
  • shakapacker:

    • Shakapacker.config and configuration classes
    • Shakapacker::Helper module
    • Manifest and compiler interfaces

Phase 2: Helper Modules & Utilities (Week 3-4)

  • View helpers and rendering methods
  • Internal utilities with public interfaces
  • Error classes and exceptions

Phase 3: Internal APIs (Optional, as needed)

  • Private methods used across multiple files
  • Complex internal data structures
  • Integration points

Example

Before (no type information):

# lib/react_on_rails/helper.rb
def react_component(name, props = {}, options = {})
  # ...
end

After (with RBS):

# lib/react_on_rails/helper.rb (unchanged)
def react_component(name, props = {}, options = {})
  # ...
end
# sig/react_on_rails/helper.rbs (new)
module ReactOnRails
  module Helper
    def react_component: (
      String name,
      ?Hash[untyped, untyped] props,
      ?Hash[Symbol, untyped] options
    ) -> String
  end
end

Implementation Checklist

  • Create sig/ directory structure
  • Add RBS to development dependencies
  • Document RBS usage in CONTRIBUTING.md
  • Start with Phase 1 APIs
  • Set up type checking in CI (optional, can defer)
  • Add examples to documentation

Resources

Questions for Discussion

  1. Should we start with shakapacker or react_on_rails first?
  2. Do we want to enable type checking in CI, or just provide signatures?
  3. Should we include type signatures for internal/private APIs?

Success Criteria

  • Core public APIs have complete RBS signatures
  • IDE autocomplete works for main methods
  • No negative impact on existing users (backward compatible)
  • Documentation updated to reference type signatures

Note: This is a non-breaking enhancement. RBS files are optional and don't affect runtime behavior for users who don't use them.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions