Rails应用中Sorbet类型别名应声明在何处?
Sorbet类型别名在Rails中的正确声明位置
问题原因
你在sorbet/rbi/shims/timestamp.rbi中定义的类型别名仅对Sorbet静态检查(srb tc)生效——因为shims/目录下的RBI文件是Sorbet专属的静态类型补充文件,Ruby运行时不会加载这些文件,所以RSpec执行时会抛出uninitialized constant错误。
解决方案
根据类型别名的使用范围,选择以下两种方式:
1. 全局可用的类型别名
如果需要在整个应用中使用Timestamp,在app/目录下创建一个专门存放类型定义的Ruby文件(Rails会自动加载app/下的文件):
# app/types/timestamp.rb # 同时定义运行时常量和Sorbet类型别名 Timestamp = T.type_alias { T.any(Time, ActiveSupport::TimeWithZone) }
这样既满足Sorbet静态检查的需求,又能让Ruby运行时识别到Timestamp常量。
2. 仅在特定类/模块内使用的类型别名
如果Timestamp只在ShowamiService中使用,直接在服务类的源码里声明类型别名:
# app/services/showami_service.rb class ShowamiService # 在类内部定义类型别名 Timestamp = T.type_alias { T.any(Time, ActiveSupport::TimeWithZone) } sig { params(availabilities: T::Array[OrderAvailability], now: Timestamp).returns(T.nilable(Timestamp)) } def calculate_local_start_at_from(availabilities, now) # 业务逻辑实现 end end
这种方式避免了全局常量污染,同时确保静态检查和运行时都能正常识别。
补充说明
- Sorbet的RBI文件分为多种类型:
shims/用于补全第三方库的静态类型,运行时不加载;而自定义的应用代码RBI文件(如sorbet/rbi/app/下的)若要运行时生效,需要额外配置,但直接在Ruby源码中定义类型别名是最可靠的方式,兼顾静态检查和运行时需求。
内容的提问来源于stack exchange,提问作者François Beausoleil
相关产品推荐
相关产品推荐

