module B
sig { returns(String) }
def current_user
@user ||= T.let(ENV.fetch('USER'), T.nilable(String))
end
end
T.class_of
: for a singleton class
T::Class
: for class types
class Resolve
extend(T::Sig)
extend(T::Generic)
ReturnT = type_member
sig { returns(T::Class[ReturnT]) }
def resolve = raise
end
module A; end
class B; include A; end
sig { returns(T::Class[A]) }
def foo = B
x = T.let(0, T.nilable(Integer))
return if x.nil?
T.reveal_type(x)
class MonetaryAmount < T::Struct
prop :amount, Integer
const :currency, String
end
class Suit < T::Enum
enums do
Spades = new
Hearts = new
Clubs = new
Diamonds = new
end
end
class User
extend(T::Sig)
sig { returns(T.attached_class) }
def self.make
new
end
sig { returns(T.self_type)}
def validate
# validation
self
end
end
sig { type_parameters(:T).params(v: T.type_parameter(:T)).returns(T::Array[T.type_parameter((:T))])}
def to_array(v)
[v]
end
sig { returns({ foo: Integer, bar: [Integer, Integer] }) }
def foo
{ foo: 1, bar: [1, 2] }
end
class Factory
extend(T::Sig)
extend(T::Generic)
KlassT = type_template
class << self
extend(T::Sig)
sig { returns(T::Class[KlassT]) }
attr_accessor(:klass)
sig { returns(KlassT) }
def make = klass.new
end
end
:out - covariant (value is produced by some computation in the method) :in - contravariant
class Animal; end
class Mammal < Animal; end
class Cat < Mammal; end
class Zoo
extend(T::Sig)
extend(T::Generic)
SelfT = type_member(:out)
sig { returns(SelfT) }
def get = raise
end
sig { params(zoo: Zoo[Mammal]).void }
def collector(zoo)
zoo.get # do mammal things
end
collector(Zoo[Cat].new)
class Animal; end
class Mammal < Animal; end
class Cat < Mammal; end
class Zoo
extend(T::Sig)
extend(T::Generic)
SelfT = type_member(:in)
sig { params(elem: SelfT).void }
def set(elem) = raise
end
sig do
params(zoo: Zoo[Mammal]).void
end
def provider(zoo)
zoo.set(Cat.new)
zoo.set(Mammal.new)
end
provider(Zoo[Animal].new)
module
extend(T::Helpers)
requires_ancestor { Kernel }
def foo
raise
end
end