冰糕中的递归 type_alias
Recursive type_alias in sorbet
如何声明一个可以包含对自身的引用的类型别名?例如标记一个函数返回一个 JSON-like 结构。
正在尝试:
Foo = T.type_alias { T.any(Integer, T::Array[Foo]) }
出现以下错误:
Type alias Foo
is involved in a cycle
从版本 0 开始。5.x,这是不可能的,因为类型别名不支持循环。
一种选择是降低结果的类型化程度,并使其成为:
Foo = T.type_alias { T.any(Integer, T::Array[T.untyped]) }
如果你真的想要类型检查,你可以通过将结果包装在 T::Struct
中来表达这样的东西。不过,对象将不再像原来那样平坦(参见 sorbet.run):
class Foo < T::Struct
prop :content, T.any(Integer, T::Array[Foo])
end
myFoo = Foo.new(content: 1)
content = myFoo.content
case content
when Integer
puts "It was an integer!"
T.reveal_type(content)
when Array
puts "It was a Foo!"
T.reveal_type(content)
else
T.absurd(content)
end
编辑 (2022-02):关于 type_alias
has been updated to address recursive definitions. It includes an example for JSON-like structures in sorbet.run 的文档。
如何声明一个可以包含对自身的引用的类型别名?例如标记一个函数返回一个 JSON-like 结构。
正在尝试:
Foo = T.type_alias { T.any(Integer, T::Array[Foo]) }
出现以下错误:
Type alias
Foo
is involved in a cycle
从版本 0 开始。5.x,这是不可能的,因为类型别名不支持循环。
一种选择是降低结果的类型化程度,并使其成为:
Foo = T.type_alias { T.any(Integer, T::Array[T.untyped]) }
如果你真的想要类型检查,你可以通过将结果包装在 T::Struct
中来表达这样的东西。不过,对象将不再像原来那样平坦(参见 sorbet.run):
class Foo < T::Struct
prop :content, T.any(Integer, T::Array[Foo])
end
myFoo = Foo.new(content: 1)
content = myFoo.content
case content
when Integer
puts "It was an integer!"
T.reveal_type(content)
when Array
puts "It was a Foo!"
T.reveal_type(content)
else
T.absurd(content)
end
编辑 (2022-02):关于 type_alias
has been updated to address recursive definitions. It includes an example for JSON-like structures in sorbet.run 的文档。