rubystatic-typingsorbetruntime-type

Sorbet does not check runtime type of an arg if it's an array


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?


Solution

  • 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 class Array, but not whether every element of that array is also an Integer at runtime.