I have the following code that you can just copy&paste locally and run it as a single file:
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'sorbet-runtime'
end
require 'sorbet-runtime'
class Numbers
extend T::Sig
sig { params(a: Integer, b: Integer).returns(Integer) }
def sum_of_two(a, b)
a + b
end
sig { params(values: T::Array[Integer]).returns(Integer) }
def sum_of_array(values)
values.sum
end
end
If I add the following lines at the end of the file I'll get the following results
Numbers.new.sum_of_two(1, 2) # => does not fail because the actual args are ints
# Numbers.new.sum_of_two(1.0, 2) # => raises errors because one of the param is Float
Numbers.new.sum_of_array([1, 2, 3]) #=> ok, because everything matches
Numbers.new.sum_of_array([1.0, 2, 3]) #=> raises only an error when tries to match the return type
Please, could anybody explain to me why it behaves like this? Why does not it verify a type in runtime if the type is an array?
This exact situation is discussed in the Documentation:
Sorbet completely erases generic type arguments at runtime. When Sorbet sees a signature like
T::Array[Integer]
, at runtime it will only check whether an argument has classArray
, but not whether every element of that array is also anInteger
at runtime.