Merry Christmas! Today Ruby 3.0 was released today with type checking. Here’s how to try it out yourself. First, read about Ruby 3.0 type checking here in The State of Ruby 3 Typing.
Install Ruby 3.0 with rbenv
To follow along, you’ll need Ruby 3.0. I use
rbenv. To see the new version 3.0, I updated
ruby-version using home brew.
brew upgrade ruby-build
Next, I was able to install the new version using
rbenv install 3.0.0
After that, I created a new directory to experiment in.
mkdir PizzaFactory cd PizzaFactory
I created a .ruby-version file to make sure
rbenv was running Ruby 3.0.
echo "3.0.0" > .ruby-version
Double-check you are running Ruby 3.0
You should see the following print out:
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]
Define a Pizza class
I created a
pizza.rb ruby file.
class Pizza attr_accessor :toppings def initialize(toppings) @toppings = toppings end def to_s toppings.join(", ") end end
Annotate the Pizza class with types using an RBS file
Next, I created a
sig/pizza.rbs file to describe the types I’ll be using.
class Pizza attr_accessor toppings: Array[String] def initialize: (Array[String]) -> void def to_s: () -> String end
Check the types with Steep
steep to do type checking. I found the steep readme on github helpful:
gem install steep
steep init and it created a
Steepfile file, which I modified as shown.
target :pizza do signature "sig" check "*.rb" end
I was curious if
steep could help me find errors. I created an
app.rb file that deliberately included a type error.
require_relative "./pizza" # Correct type should be: Array[String] # pizza = Pizza.new(["Pepperoni", "Green Peppers"]) # Incorrect type is passed instead: String pizza = Pizza.new("Coffee") puts pizza.to_s
Check for type errors:
Success! Well, success in that it found the error I deliberately put in
app.rb:4:18: ArgumentTypeMismatch: receiver=singleton(::Pizza), expected=::Array[::String], actual=::String ("Coffee")
I’ve tried Sorbet briefly too, and I’m not sure yet whether I prefer inline type annotations or external rbs files. Also, hiding the type annotations in a ‘sig’ folder seems a bit odd. I’m used to .h files being in the same directory as their counterpart, and rbs files seem similar to a header file to me. I do love the rbs syntax though.
Kudos to all the developers working on improving Ruby and making the ecosystem richer with type checking. Thank you!