Ruby sorbet: Difference between revisions
From wikinotes
No edit summary |
(→Usage) |
||
Line 21: | Line 21: | ||
bundle exec srb tc --help 2>&1 | less -Ri # show help in less | bundle exec srb tc --help 2>&1 | less -Ri # show help in less | ||
bundle exec srb tc 2>&1 | grep -C5 ClassICareAbout # check for errors in specific class | bundle exec srb tc 2>&1 | grep -C5 ClassICareAbout # check for errors in specific class | ||
</source> | |||
You can also use sorbet as an LSP. | |||
<source lang="bash"> | |||
srb tc --lsp | |||
</source> | </source> | ||
</blockquote><!-- Usage --> | </blockquote><!-- Usage --> |
Revision as of 06:07, 28 December 2021
Implements static typing for ruby.
You may also be interested in ruby tapioca to automatically generate rbi files.
Documentation
homepage https://sorbet.org/ github https://github.com/sorbet/sorbet gem src (no apidocs) https://github.com/sorbet/sorbet/tree/master/gems sig documentation https://sorbet.org/docs/sigs
Usage
bundle exec srb tc --help 2>&1 | less -Ri # show help in less bundle exec srb tc 2>&1 | grep -C5 ClassICareAbout # check for errors in specific classYou can also use sorbet as an LSP.
srb tc --lsp
Basics
# person.rb class Person def create(name:, age:, object:); end def speak; "foo"; end end# person.rbi class Person extend T::Sig # adds 'sig' method extend T::Helpers # adds 'requires_ancestor, abstract!, interface!, sealed!, ...' methods sig { params(name: ::String, age: ::Integer, object: T.untyped).void } def create(name:, age:, object:); end sig { returns(String) } def speak; "foo"; end end
Common 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 used
Tools
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
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 end