Sorbet syntax
From wikinotes
The docs for sorbet are really, really good.
I'd probably just go there.
Basics
# person.rb class Person def create(name:, age:, object:); end def speak; "foo"; end endCommon Cases
attr_reader/writer/accessor
sig { returns(String) } attr_reader :nameinclude module
require_ancestors https://sorbet.org/docs/requires-ancestor mix_in_class_methods https://sorbet.org/docs/abstract instance methods should just work
module AnimalMethods sig { returns(T.void) } def walk(); end end class Cat include AnimalMethods endclass methods
module AnimalMethods extend T::Sig extend T::Helpers # modify to set classmethods on include def self.included(base = nil) base&.extend(ClassMethods) end # define classmethods module ClassMethods sig { returns(String) } def speak(); end end # inform sorbet of classmethods mixes_in_class_methods ClassMethods end class Cat include AnimalMethods endrails concerns && included do
procs/lambdas
sig { params(block: T.proc.params(arg0: Integer).void).void } def foo(&block)If your proc is designed to be executed in a different context
(for example, proc is set as a class method, but designed to run on a class instance)
you can useT.bind(self, YourClass)
.Types
# stdlib types String Symbol Integer Float NilClass # generic types T::Array[Integer] T::Set[Integer] T::Hash[Symbol, String] T::Enumerable[Integer] T::Enumerator[Integer] T::Range[Integer] # sorbet types T::Boolean # true/false T.untyped # anything T.nilable(String) # Unions: string or nil T.any(String, Integer) # Unions: either string or integer T.noreturn # if method never returns (exception, exit process, loop forever, ...) sig { params(...).void } # ignore return value, not meant to be usedGenerics
# a generic method, that takes param of arbitrary type 'T' and returns type 'T' sig do type_parameters(:T) .params(var: T.type_parameter(:T)) .returns(T.type_parameter(:T)) end def foo(var) var endTools
T.type_alias T.bind(self, YourClass) # use within proc, to indicate the instance it should be executed in (defaults to current) T.cast(var, YourClass) mixes_in_class_methods ClassMethods # when class included, ClassMethods become static methods on target class requires_ancestor Kernel # any class that includes this module, must also include Kernel T::Utils # provided by sorbet-runtime, tools for getting information about sigs, adding sigs, etc.Tricks
Type Aliases
You can define re-usable type-sigs with type aliases.
class University extend T::Sig StudentMap = T.type_alias { T::Hash[Symbol, String] } sig { params(student_map: StudentMap).returns(Integer) } def count_students(student_map) student_map.count end sig { params(student_map: StudentMap).returns(List[String]) } def name_students(student_map) student_map.keys() end endDynamically setting a Type Signature
class Foo sig { params(a: Integer).void } def bar(a) = nil end T::Private::Methods.declare_sig(Foo, nil, :final) { params(a: String).void } declaration = T::Private::DeclState.current.active_declaration T::Private::Methods.run_sig(Foo, :bar, Foo.instance_method(:bar), declaration) # voila! signature installed T::Utils.signature_for_instance_method(Foo, :bar)