Skip to content

Instantly share code, notes, and snippets.

@itarato
Last active March 27, 2025 12:13
Show Gist options
  • Save itarato/1285f934dce5507bed4d1e38293b9f0f to your computer and use it in GitHub Desktop.
Save itarato/1285f934dce5507bed4d1e38293b9f0f to your computer and use it in GitHub Desktop.
Sorbet Basics

Sig

T.let

T.must / T.cast

T.nilable

Lazy initialization

module B
  sig { returns(String) }
  def current_user
    @user ||= T.let(ENV.fetch('USER'), T.nilable(String))
  end
end

T.any / T.all

Arrays / Sets / Hashes

T.class_of / T::Class

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

Type narrowing flow

x = T.let(0, T.nilable(Integer))
return if x.nil?
T.reveal_type(x)

T.type_alias

Exhaustiveness

T::Struct / T::Enum

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

Abstract classes and interfaces (and sealed)

T.self_type / T.attached_class

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

T.noreturn

T.type_parameter

sig { type_parameters(:T).params(v: T.type_parameter(:T)).returns(T::Array[T.type_parameter((:T))])}
def to_array(v)
  [v]
end

Tuples and shapes

sig { returns({ foo: Integer, bar: [Integer, Integer] }) }
def foo
	{ foo: 1, bar: [1, 2] }
end

Generics

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

:in / :out

: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)

:upper / :lower / :fixed

Require ancestor

module
	extend(T::Helpers)

	requires_ancestor { Kernel }

	def foo
		raise
	end
end

T.unsafe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment