Soutaro Matsumoto

The State of Ruby 3 Typing

Ruby 3 will ship with a new feature for type checking, RBS. It provides a language to describe types of Ruby programs, the type declarations for standard library classes, and a set of features to support using and developing type checkers. In this talk, I will introduce the feature and how the Ruby programming will be with RBS.

RubyKaigi Takeout 2020

00:00:01.199 Hello, my name is Soutaro Matsumoto. I am an engineer working for Square in Tokyo. I write some Rails applications and I'm also working to improve the development environment. I developed a type checker called Steve and I'm running an experiment to test Steve with some of the projects in the company. Additionally, I'm a member of the Adobe community team and I'm working on types in the team as well.
00:00:15.679 The topic of my talk today is the state of Ruby 3 typing. Ruby 3 will ship with a new feature called RBS to support type checkers. RBS is both the name of the language used to declare types in Ruby programs and the name of an Adobe gem bundled with Ruby 3. This gem provides features to read, write, and process type definitions written in RBS, and it includes type definitions for standard library classes.
00:00:41.920 You can start using the standard library and its type definitions just after installing Ruby 3. One important note is that Ruby 3 won't provide a standard type checker. The Ruby core team is not attempting to endorse a single 'best' type checker, so you will need to choose the best type checker for your team and project.
00:01:02.159 I would like to introduce some type checkers for Ruby that you can choose from. Steve, which I mentioned earlier, is a type checker written in Ruby. Sorbet is currently the most widely used type checker for Ruby. You may find discussions on its usage within the Ruby community. Another option is Type Profiler, which infers types in programs without any explicit type annotations.
00:01:32.799 RDL is another project that serves as a research tool in development. The team is led by Professor Foster, who has published research papers on type checking for Ruby using this tool. These papers are quite interesting, and I encourage you to check them out online. Therefore, we have at least four type checkers available for Ruby.
00:01:52.240 Now, let's discuss the idea of static type checking. Consider an example Ruby program that prompts several questions. For instance, if there is a new method called `unconference_constant`, a question arises: does this method accept a string argument, or does it require other arguments? Similarly, when looking at the `talks` method, which uses the `push` method of an array, you might wonder about the return type of the `talks` method. It appears to return an array, but we can't be certain.
00:02:21.440 Furthermore, the `each_speaker` method suggests it accepts blocks, but the type of block arguments is uncertain. Perhaps it expects an instance of a speaker, but again, we can't be sure without the correct type definitions. Questions like these illustrate why static type checking is beneficial; it would return answers without executing the Ruby program.
00:02:39.600 If we execute the Ruby program, the interpreter will give answers based on the provided code. For example, it will raise an ArgumentError if required arguments are missing. Other exceptions may arise if there are method naming errors. However, identifying type problems statically rather than through execution would be a significant improvement.
00:03:06.720 RBS can assist with static type checking by clarifying methods' expectations and preventing potential runtime errors. The RBS language allows developers to define types for Ruby applications including classes, modules, methods, and the relationships between them. In essence, RBS acts as documentation for what types are available and how they should be used in Ruby code.
00:03:40.720 To illustrate the utility of RBS, consider the `Conference` class as an example. It has two read-only attributes, `name` (a string) and `talks` (an array of Talk objects). The `schedule` method accepts one string argument, while the `each_speaker` method expects a block to operate on, indicating the structure and type relationships throughout the class.
00:04:00.480 Using RBS for the Conference class allows developers to ascertain the return types and expected method arguments at a glance, which is invaluable for development. By having well-defined interfaces, we can quickly identify how to interact with different objects, providing a clearer documentation of the code.
00:04:20.720 RBS is not limited to simple classes; it can be applied to the standard libraries. For example, you may find RBS files for the String class, detailing the methods and their respective types. Through various advanced types supported in RBS, we can implement generics, union types, and optional types, allowing for flexible and precise type definitions.
00:04:44.080 The concept of generics means we can define a type that takes other types as parameters, such as an array of integers or a hash with string keys and integer values. Union types let us specify a value that can be one of several types, while optional types provide shortcuts for expressing variables that may be nil. Additionally, we have support for duck typing, allowing a type to represent any object that implements specific methods regardless of inheritance.
00:05:53.600 In RBS, there is a special type known as 'untyped,' which indicates that the type checker will not perform any checks on that type, akin to the `any` type in TypeScript. More examples and detailed specifications can be found in the RBS repositories, which contain RBS files for standard libraries, thus making it easier for developers to use.
00:06:32.000 The language RBS itself is designed to enable better type checking in Ruby applications. It facilitates the definition of types outside of the Ruby code, accounting for projects implemented in the C language, such as the Ruby standard library. The architects of RBS believe that modular type development and clear interface definitions are paramount for Ruby's ongoing evolution.
00:07:26.400 The RBS library aids developers in creating type checkers without constraining them to a fixed type definition format. It allows developers to focus on core features while it manages the complexities of type declarations. Tools like RBS must offer compatible interfaces across multiple type checkers while ensuring ease of adoption within existing projects.
00:08:45.920 Expect that as Ruby continues to evolve, so too will RBS and the community's perception of static typing. Eventually, developers may rely more heavily on static type definitions to prevent runtime errors before they occur. However, these practices should remain optional, encouraging developers unfamiliar or uncomfortable with types to ease into the concept.
00:09:29.680 Ultimately, the RBS project aims to be a bridge between dynamic Ruby programming and the advantages of static typing, contributing positively to developer experience and application reliability. It represents a significant advancement in Ruby language features and brings new opportunities for enhancing code quality.
00:10:11.679 As Ruby 3 rolls out, expect RBS files to be a staple in modern Ruby applications. Each Ruby application should take advantage of RBS for documenting standard libraries and the specific types used. Keeping types in separate RBS files helps enhance code understanding and limit errors without forcing adoption of strict typing policies at the project level.
00:10:49.440 Thank you for watching my presentation. While I believe RBS is an exciting addition to Ruby, I also recognize there are challenges and gaps that still need to be addressed. Please feel free to reach out to me on Twitter or GitHub if you have any questions or feedback. I appreciate your time.