I'm a big fan of Ruby, but God I wish it had good, in-line type hinting. Sorbet annotations are too noisy and the whole thing feels very awkwardly bolted on, while RBS' use of external files make it a non-starter.
I'm a big fan of Ruby, but God I wish it had good, in-line type hinting. Sorbet annotations are too noisy and the whole thing feels very awkwardly bolted on, while RBS' use of external files make it a non-starter.
I am one of the authors of RDL (https://github.com/tupl-tufts/rdl) a research project that looked at type systems for Ruby before it became mainstream. We went for strings that looked nice, but were parsed into a type signature. Sorbet, on the other hand, uses Ruby values in a DSL to define types. We were of the impression that many of our core ideas were absorbed by other projects and Sorbet and RBS has pretty much mainstream. What is missing to get usable gradual types in Ruby?
Sorbet type annotations are noisy, verbose, and are much less easy to parse at a glance than an equivalent typesig in other languages. Sorbet itself feels... hefty. Incorporating Sorbet in an existing project seems like a substantial investment. RBS files are nuts from a DRY perspective, and generating them from e.g. RDoc is a second rate experience.
More broadly, the extensive use of runtime metaprogramming in Ruby gems severely limits static analysis in practice, and there seems to be a strong cultural resistance to gradual typing even where it would be possible and make sense, which I would - at least in part - attribute to the cumbersome UX of RBS/Sorbet, cf. something like Python's gradual typing.
Gradual typing isn't technically impossible in Ruby, it just feels... unwelcome.
When I do need types inline I believe it is the editor's job to show them dynamically, e.g via facilities like tooltips, autocompletion, or vim inlay hints and virtual text, which can apply to much more than just signatures near method definitions. Types are much more useful where the code is used than where it is defined.
I follow a 1:1 lib/.rb - sig/.rbs convention and have projection+ files to jump from one to the other instantly.
And since the syntax of RBS is so close to Ruby I found myself accidentally writing things type-first then using that as a template to write the actual code.
Of note, if you crawl soutaro's repo (author of steep) you'll find a prototype of inline RBS.
+ used by vim projectionist and vscode projection extension