How to typify a Ruby gem, by Vladimir Dementyev
Abstract
Ruby introduced optional types support almost three years ago. Still, we can’t say many projects adopted RBS or Sorbet. One of the reasons is that only a tiny portion of Ruby gems provide type signatures. This situation slows down the adoption of types for those relying on untyped third-party libraries. Sure, not everyone needs types, but even those who might benefit from them struggle with the first steps.
Getting started with types in Ruby can be tricky, especially in large monolithic codebases. Typification is more approachable if you develop a library.
In my talk, I’d like to share tips on how to get started with using types (RBS) in gems, so you can both practice typifying Ruby code and bring value to others by shipping your code with type signatures.
Details
The talk aims to demonstrate how to you Ruby types in gems. We will talk about two perspectives here: providing type signatures for your code and fully utilizing types in gems development. The former (adding `sig/` to your gem’s package) is much easier to do and doesn’t require much effort from gem maintainers; anyone can do that with just a bit of guidance. The latter can be tricky and need more resources (time), while it can pay off in the long term.
Thus, the audience of this talk is everyone from those who are just starting with building Ruby libraries and curious about types to seasoned gem authors who are looking for an efficient and less time-consuming way of introducing types to their codebases and leveraging typed code benefits.
In the introductory part of the talk, I’d like to start with some basic intro to RBS and the current state of the typification in Ruby. I want to calculate the exact numbers closer to the event; the goal is to see how many gems among the most downloaded in the last 3 years provide type signatures or have third-party type signatures available. Given the numbers, we can discuss what’s our goal. Do we want all gems to have types or not? Even though types are optional and not every project needs them, there are definitely use cases when types help build software with Ruby. Thus, at least having types for the public API of your gem is beneficial (and that doesn’t mean you must fully cover your code with types).
That leads us to the first part of the talk—shipping types along with the library’s code. Here I want to share some practical tips on adding types to public APIs without enforcing type safety for the project itself. We’re going to talk about TypeProf, gem specification, RBS runtime checks in tests, and custom type generators for DSLs.
Then, we take the next step and discuss how to utilize types and use them in gem development fully. Here we talk about Steep, its configuration, and some tips on using it (such as using \@annotations). We also discuss the problem of missing third-party signatures and how to obtain them and configure gemspec/Steep to only use them for gem development without exporting.
In the end, gem developers (current and future) will learn about the required steps to get their libraries types-friendly, as well as some tips on how to do that with less friction.
Pitch
I’ve been experimenting with Ruby types systems since their very first days. Starting with Sorbet and gradually migrating to RBS and Steep, I’ve been integrating types into my libraries (and even larger projects). I found types more useful than useless for gems development. Still, at the same time, I understand why developers may resist adding types to their projects: the ecosystem is still young, and tools are breaking-changing quite often. It adds an additional burden for maintainers. And we’re talking about open-source—maintainers already sacrifice their spare time, why encourage them to spend more? We can’t demand this. But we can help to make it easier to adopt new Ruby ideas.
My goal is to help Ruby gems developers to adopt types and bring more value to the ecosystem. Only after I typified 3-4 of my gems, I came up with the process, which is not painful. And now, I want to share it with the community.