从 0.4.4679 开始,Sorbet 现在已经内置了对此的支持。在此之前,还有其他解决方法(见下文)。
- 将实例变量初始化为
T.nilable
,并将在别处对实例变量的所有直接访问替换为方法:
# typed: strict
# frozen_string_literal: true
module Util
extend T::Sig
sig { returns(String) }
def self.git_sha
@git_sha = T.let(@git_sha, T.nilable(String))
@git_sha ||= ENV.fetch(
'GIT_REV',
`git rev-parse --verify HEAD 2>&1`
).chomp
end
end
→ 在 sorbet.run 上查看
这是首选的解决方案。
- 在方法之外初始化实例变量,并给它一个类型注释:
# typed: strict
# frozen_string_literal: true
module Util
extend T::Sig
@git_sha = T.let(nil, T.nilable(String))
sig { returns(String) }
def self.git_sha
@git_sha ||= ENV.fetch(
'GIT_REV',
`git rev-parse --verify HEAD 2>&1`
).chomp
end
end
→ 在 sorbet.run 上查看
从概念上讲,这个类有两个执行阶段:初始化时和使用时。如果一个实例变量在 Sorbet 中初始化时没有给出类型注释,它将T.untyped
无处不在(或在 中出现错误# typed: strict
)。因为如果在初始化时没有注解,Sorbet 就无法知道哪个代码路径可能先写入这个位置。(即使在这种只有一个位置的情况下,Sorbet 也不会进行那种全局分析。)
Sorbet 仅在实例变量为 nil 时才放宽这一点,在这种情况下,它可以在任何地方初始化,因为 Sorbet 不需要保证它被初始化为非 nil。
- 使用不同的严格级别。
关于严格程度的文档。
如果您发现添加类型注释太繁琐,您可以通过 using 选择不要求类型注释# typed: true
,其中需要实例变量的类型注释的错误被静音。