|
|
(10 intermediate revisions by the same user not shown) |
Line 16: |
Line 16: |
| </blockquote><!-- documentation --> | | </blockquote><!-- documentation --> |
|
| |
|
| = Usage = | | = Notes = |
| <blockquote>
| |
| <source lang="bash">
| |
| 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
| |
| </source>
| |
| | |
| You can also use sorbet as an LSP.
| |
| <source lang="bash">
| |
| srb tc --lsp
| |
| </source>
| |
| </blockquote><!-- Usage -->
| |
| | |
| = Basics =
| |
| <blockquote>
| |
| <source lang="ruby">
| |
| # person.rb
| |
| | |
| class Person
| |
| def create(name:, age:, object:); end
| |
| def speak; "foo"; end
| |
| end
| |
| </source>
| |
| | |
| <source lang="ruby">
| |
| # 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
| |
| </source>
| |
| </blockquote><!-- basics -->
| |
| | |
| = Common Cases =
| |
| <blockquote>
| |
| == attr_reader/writer/accessor ==
| |
| <blockquote>
| |
| <source lang="ruby">
| |
| sig { returns(String) }
| |
| attr_reader :name
| |
| </source>
| |
| </blockquote><!-- attr_reader/writer/accessor -->
| |
| | |
| == include module ==
| |
| <blockquote> | | <blockquote> |
| {| class="wikitable" | | {| class="wikitable" |
| |- | | |- |
| | require_ancestors || https://sorbet.org/docs/requires-ancestor | | | [[sorbet install]] |
| |- | | |- |
| | mix_in_class_methods || https://sorbet.org/docs/abstract | | | [[sorbet usage]] |
| | |- |
| | | [[sorbet confguration]] |
| | |- |
| | | [[sorbet syntax]] |
| |- | | |- |
| |} | | |} |
| | | </blockquote><!-- Notes --> |
| instance methods should just work
| |
| <source lang="ruby">
| |
| module AnimalMethods
| |
| sig { returns(T.void) }
| |
| def walk(); end
| |
| end
| |
| | |
| class Cat
| |
| include AnimalMethods
| |
| end
| |
| </source>
| |
| | |
| class methods
| |
| <source lang="ruby">
| |
| 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
| |
| end
| |
| </source>
| |
| | |
| rails concerns && included do
| |
| <source lang="ruby">
| |
| | |
| </source>
| |
| </blockquote><!-- include module -->
| |
| | |
| == procs/lambdas ==
| |
| <blockquote>
| |
| <source lang="ruby">
| |
| sig { params(block: T.proc.params(arg0: Integer).void).void }
| |
| def foo(&block)
| |
| </source>
| |
| | |
| If your proc is designed to be executed in a different context<br>
| |
| (for example, proc is set as a class method, but designed to run on a class instance)<br>
| |
| you can use <code>T.bind(self, YourClass)</code>.
| |
| </blockquote><!-- procs/lambdas -->
| |
| </blockquote><!-- Common Cases -->
| |
| | |
| = Types =
| |
| <blockquote>
| |
| <source lang="ruby">
| |
| # 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
| |
| </source>
| |
| </blockquote><!-- Types -->
| |
| | |
| = Tools =
| |
| <blockquote>
| |
| <source lang="ruby">
| |
| 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
| |
| </source>
| |
| </blockquote><!-- Tools -->
| |
| | |
| = Tricks =
| |
| <blockquote>
| |
| == Type Aliases ==
| |
| <blockquote>
| |
| You can define re-usable type-sigs with type aliases.
| |
| <source lang="ruby">
| |
| 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
| |
| </source>
| |
| </blockquote><!-- Type Aliases -->
| |
| </blockquote><!-- Tricks --> | |