You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sorbet为何不检查数组类型参数的运行时类型?

Sorbet数组参数运行时类型检查不触发的原因分析

基础代码示例

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

测试代码及现象

Numbers.new.sum_of_two(1, 2) # => 因实际参数均为整数,无报错
# Numbers.new.sum_of_two(1.0, 2) # => 因其中一个参数为Float,触发错误
Numbers.new.sum_of_array([1, 2, 3]) #=> 参数匹配,运行正常

Numbers.new.sum_of_array([1.0, 2, 3]) #=> 仅在匹配返回类型时才抛出错误

问题

为何会出现这种行为?为何当参数类型为数组时,Sorbet不执行运行时类型检查?

解答

核心原因:Sorbet的泛型运行时检查策略

  • 基础类型与泛型类型的检查差异:sorbet-runtime对单个基础类型(如Integer)会做即时的严格参数类型检查,但对于T::Array[Integer]这类泛型集合,默认仅检查参数是否为Array实例,不会递归校验集合内的元素类型。这是出于性能考量——递归检查大量集合元素会显著增加运行时开销。
  • 报错的真实触发点:sum_of_array([1.0, 2, 3])的报错并非来自参数类型检查,而是因为数组包含Float元素,调用sum后返回Float类型,与方法签名声明的返回值Integer不匹配,触发了返回值的类型校验错误。

如何启用集合元素的运行时检查

如果需要强制校验数组内的元素类型,可以使用T.cast显式校验:

# 显式校验数组元素类型,触发参数错误
validated_array = T.cast([1.0, 2, 3], T::Array[Integer])
Numbers.new.sum_of_array(validated_array)

内容的提问来源于stack exchange,提问作者Rostislav Zhuravsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:25:48