T-Ruby Is Ruby with Syntax for Types
Key topics
The emergence of T-Ruby, a version of Ruby with type syntax, has sparked a lively debate about the merits of gradual typing in programming languages. Some commenters, like wawj, argue that T-Ruby makes sense for Ruby developers seeking the safety of statically typed languages like C#. Others, such as ReflectedImage, counter that gradual typing is "the worst of both worlds," citing increased complexity and slower development times. However, jaapz and others share opposing anecdotal evidence, having successfully added types to large codebases without sacrificing speed or simplicity. As the discussion unfolds, it becomes clear that the value of gradual typing depends on individual experiences and perspectives.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
5h
Peak period
82
0-12h
Avg / period
21.1
Based on 148 loaded comments
Key moments
- 01Story posted
Dec 26, 2025 at 3:27 PM EST
12 days ago
Step 01 - 02First comment
Dec 26, 2025 at 8:47 PM EST
5h after posting
Step 02 - 03Peak activity
82 comments in 0-12h
Hottest window of the conversation
Step 03 - 04Latest activity
Jan 3, 2026 at 9:19 AM EST
4d ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
I like typescript and I think it makes sense:, the web makes you married to JavaScript, so it’s the reasonable path forward if you want types in that context.
But what is the point of the recent wave of types for python, Ruby, and similar languages?
If it’s type safety you want there, there’s a bajillion other languages you can use right?
I disagree that you get the same safety as C# anywhere though. But even more importantly - I don't think people should write C#-like code in ruby. It does not really work that well. It is better to write ruby like ruby; and even in ruby there are many different styles. See zverok using functional programming a lot. I stick to oldschool boring OOP; my code is very boring. But usually well-documented. I want to have to think as little as possible because my brain is very inefficient and lazy; zverok has a good brain so he can write more complex code. It is very alien code to me though, but he also documents his code a lot. You can find his code or some of his code here, it is a quite interesting ruby style, but also alien to me: https://zverok.space/projects/
(Ruby also adopted some habits from perl. I also don't think writing perl-like ruby makes a lot of sense. See also the old global variables inspired by perl; I can not recall most of them off-hand, so I avoid using them. My brain really needs structure - it is such a poor thinking machine really. And slow. My fingers are much faster than my brain really.)
You get the complexity and slower development times of using statically typed languages along with the bad performance of using dynamically typed languages.
As always, no fancy new tech is a substitute for competent project management.
Common Lisp showed you the way. But almost none looked at it. Only PHP did.
Both Python and Ruby (the languages themselves) only specify the type hint syntax, but neither specifies anything about checking the actual types. That exercise is left for the implementations of third party type checkers.
But languages with stronger and more intelligent leadership showed what's possible.
You cannot implement all the compiler optimizations for const and types in extensions. You need to fork it.
They don't understand what static typing does to code verbosity and development times.
Take Turborepo going from Go's typing light system (designed to emulate duck typing) to Rust's heavy typing system (true static typing). Originally the code was 20,000 lines and was coded by 1 developer in 3 months. When moved into the typing style you like so much, the same code is now 80,000 lines and was coded by a team of developers in 14 months.
If performance wasn't an issue, then the static type based developers would all be fired. Either directly or by the businesses who relied on them getting driven into bankruptcy by their competitors. You would still get some niche jobs in it where they like to do formal verification of the code.
Your problem is just that your development skills from static type based development don't transfer to duck type based development. Different style of codebases needs to be handed completely differently.
Duck typing as done with python is the worst of both worlds. No optimizations, no enforcement. Just optional external typechecks.
Of course untyped code (ie runtime types in each var) is to write faster. You only need to add types to some vars or args, and gradually improve from there. Eg ints only, because they are optimized the easiest. No need to check for strings, bigint, floats,.... Or arrays to check for overflows at compile-time and restrict to ints or strings. Massive improvements possible, in size and runtime.
Or object fields. Hash lookups vs static offsets.
There are deeper optimizations that JITs can do such as knowing at runtime that the value of a variable is always 2 that typing information simply can't express.
Duck typed Python is optimal for development speeds, the only thing that matters in startup environments. It has it's niche.
You aren't gradually improving, you are gradually deteriorating the codebase to make it look more familar to you.
If anything, it speeds up development. Plus it helps give more confidence in the correctness of your code.
To give you a roughly idea, you should always expect a 3x slow down when using static typing.
An recent example is Turborepo that went from basic types in Go to proper static typing in Rust. Just adding in the proper typing caused the codebase to grow from 20,000 lines to 80,000 lines and from 3 developer months to 14 developer months.
The stronger your typing system, the slower you will develop code. Whether you realise it or not.
From someone who has worked mostly in Ruby (but also Perl and TypeScript and Elixir) I think for web development, a dynamic language with optional types actually hits maybe the best point for developer productivity IMO.
Without any types in a dynamic language, you often end up with code that can be quite difficult to understand what kinds of objects are represented by a given variable. Especially in older poorly factored codebases where there are often many variations of classes with similar names and often closely related functions it can feel almost impossible until you're really familiar with the codebase.
With an actual fully typed language you're much more constrained in terms of what idioms you can use and how you can express and handle code by the type system. If you're not adept or knowledgeable about these things you can spend a lot of time trying to jam what you're attempting into the type system only to eventually realize it's impossible to do.
A gradual type system on top of a dynamic language gets you some of the best of both worlds. A huge amount of the value is just getting typing at function boundaries (what are the types of the arguments for this function? what is the type of what it's returning?) but at the same time it's extremely easy to just sidestep the type system if it can't express what you want or is too cumbersome.
That is a fair opinion. My opinion is different, but that's totally fine - we have different views here.
What I completely disagree with, though, is this statement:
> Without any types in a dynamic language, you often end up with code that can be quite difficult to understand what kinds of objects are represented by a given variable.
I have been writing ruby code since about 22 years (almost) now. I never needed types as such. My code does not depend on types or assumptions about variables per se, although I do, of course, use .is_a? and .respond_to? quite a lot, to determine some sanitizing or logic steps (e. g. if an Array is given to a method, I may iterate over that array as such, and pass it recursively into the method back).
Your argument seems to be more related to naming variables. People could name a variable in a certain way if they need this, e. g. array_all_people = []. This may not be super-elegant; and it does not have as strong as support as types would, but it invalidates the argument that people don't know what variables are or do in complex programs as such. I simply don't think you need types to manage this part at all.
> Especially in older poorly factored codebases where there are often many variations of classes with similar names and often closely related functions it can feel almost impossible until you're really familiar with the codebase.
Note that this is intrinsic complexity that is valid for ANY codebase. I highly doubt just by using types, people automatically understand 50.000 lines of code written by other people. That just doesn't make sense to me.
> With an actual fully typed language you're much more constrained in terms of what idioms you can use
I already don't want the type restrictions.
> A gradual type system on top of a dynamic language gets you some of the best of both worlds.
I reason it combines the worst of both worlds, since rather than committing, people add more complexity into the system.
That said, I do like it when an LSP can show some nice method signature info, and types are helpful in that way. I think it depends. At the surface level, I like some of the niceties that type annotations can bring, but I've seen how tricky defining more complex objects can get. Occasionally I would spend way too much time fighting types in elixir with dialyzer, and I've often not enjoyed TypeScript for the verbosity. So I understand the cost of defining types. To me, the cost often outweigh the benefit of type annotation.
E.g. if you require an input to be StringIO, instead of requiring an object that responds to "read".
Too often I see people add typing (be it with a project like this, or with is_a? or respond_to?) that makes assumptions about how the caller will want to use it, rather than state actual requirements.
That is why I prefer projects to be very deliberate and cautious about how they use types, and keep it to a minimum.
Maybe this isn't a fair comparison, since I'm pretty new to OCAML and I'm sure an experience developer would have seen what was happening much quicker than I would have. But I'm not sure I spent 90 minutes TOTAL on type errors doing Python web dev.
Maybe I'm exaggerating, and I probably just don't remember the first time I hit a type error, but my experience with type errors was that I would very occasionally hit them, and then I would just fix the type error. Pretty easy.
The kind of messy code base that results from (large) numbers of (mediocre) developers hastily implementing hacky bug fixes and (incomplete) specifications under time pressure isn't necessarily solved by any technical solution such as type hints.
One of the worst parts of exploring a new codebase written in a language without type labeling is tunneling through the code trying to figure out what this thing you see being bounced around in the program like the a ball in a pinball machine actually is.
And the LLMs take advantage of the types through the LSP and type checking.
“It has a field of type X” has never been a useful test for me, my tests are always more like:
“if I send message X I get return value or action Y”
… with my admittedly limited experience of types I don’t see how they replicate this.
Therefore it looks like I’d only be “replacing” tests that I’d never write in the first place.
What am I missing?
Unit tests typically test for behaviours. This could be both positive and negative tests. But we often test only a subset of possibilities just because how people generally think (more positive cases than negative cases). Theoretically we can do all those tests with unit testing. But we need to ask ourselves honestly, do we have that kind of test coverage as SQLLite? If yes, do we have that for very large codebases?
https://sqlite.org/testing.html
For these tests we don’t care about the content only that something didn’t get incorrectly set or the mailer interface changed.
Now the compiler tells us there is an error - we don’t _necessarily_ need a test for this. Sorbet will error and say “hey you need another User object here” or you are returning nil instead of a Mail object.
I don't care much for types, but it can be useful with denser libraries where IDE's can assist with writing code. It has been helpful in my professional life with regards to typed Python and Typescript.
One potential example that would be interesting is utilizing types for reflection for AI tool calling, the python library for Ollama already supports this[0].
It would make it easier to use such tools in a Ruby context and potentially enhance libraries like ruby-llm [1] and ollama-ruby [2].
[0] https://docs.ollama.com/capabilities/tool-calling#using-func...
[1] https://rubyllm.com/
[2] https://github.com/flori/ollama-ruby
https://github.com/vicentereig/dspy.rb
the intrinsic use case is that your code is often implicitly statically typed, even if the language itself doesn't enforce that, so it's nice for tools to check it for you. this gets more and more useful the larger your codebase gets; python and javascript have shown that in practice.
and note that people have already written type checkers for ruby, they are just much less pleasant to use because there is no nice way to express the types you would like to check/enforce.
That said, I am actually in the "don't want types in Ruby" camp. Intellisense isn't as needed if you're good at using irb (the repl). And the dynamism makes it super easy to write unit tests, which can give you back a lot of the guarantees you'd otherwise get from static types. Most importantly, a lot of the fun in Ruby comes from the ability to make nice DSLs and aggressively metaprogram boilerplate away.
I think about 99% of people who suggest to slap down types onto dynamic languages have already been using types since decades, or many years, in another language. Now they switch to a new language and want to have types because their brain is used to.
A robust type system allows you to make "compiler errors" out of runtime errors. One of these takes *way more tests to catch* than the other. I'll let you guess which.
With experience you will learn to either write unit tests or spend the same amount of time doing manual testing.
Once you start doing that then the unit tests just replace the static typing and you start shipping better code to your customers.
And your suggestion that people who like static types "don't know how to write unit tests" is further bad faith.
Perhaps it's dynamic typing programmers who don't know how to write sound programs? Except I'm not making that claim, because I'm giving you all some benefit of the doubt, a degree of respect you are not giving others.
It's called ratting yourself out.
Wasteful unit tests that assert your types are right don't have much value if there is a proper type system.
> It's called ratting yourself out.
Quit being childish.
At one of my jobs, i was often plagued by not knowing if "f" - short for file, naturally, that part is fine tbh - was a string, an io-like thing, a path object, a file object, or what-have-you. Sure sure, some argue this is the magic of python - just try to do whatever you want to it, and if it doesn't work, throw an error - I know I know. I'll tell you that's all really cool until you have 8 different people passing around 8 different types and you're just trying to have the darn program not crash and also not print logs like "could not snafucate file: [whatever str/repr comes out when you print() an IO object]". And this isn't one of those cases where being able to shrug at the type is like, buying you anything. It's just a damn file.
So, when python's types came out, I started going in and type hinting f: str where i found it and could determine it was a string. (and various other things like this - obviously f is just an example). And suddenly after enough of this, we just stopped having that problem. Coworkers thanked me when they saw me in the diffs adding them. People just passed in strings.
I'll also add that in most programs, most types are just primitives, built-in collections, and structs composing those two. So while it's quite nice yes that you can do crazy backflips that would simply not work in more rigidly typed languages, often I do want to just reassure everyone that yes, please pass in a str for "file". And if i've typed it as str|IO then do feel free to also pass in an IO. It just lets me talk to the other programmers in the codebase a lot more easily. I'm not trying to enforce correctness of types necessarily. I'm just trying to communicate.
But yes, there are multiple ways to solve communication problems.
Another example - in ruby. I really like the Pathname library and use it a lot. Even in my OWN programs, where I almost ALWAYS immediately turn a path into a Pathname, I still find myself calling Pathname functions and getting errors because the type is a string. I've found myself naming parameters - lets say it's a data file - "data_pn" to reassure myself that i should indeed pass in a pathname and not a string.
This is just re-engaging the hungarian notation "warts" pattern in another place and time.
Take a working system and rewrite it as a series of separted network services in a new, trendy language just because.
It was a fad that new broom CTO were keen on 5 years ago and I've seen a few companies killed by that decision.
There's so much unnecessary added complexity in running a distributed system of ts micro-services compared to a monolith. You need to be honest about that.
The developers who are using the statically typed languages, which are slower to develop in, with are being pushed to use the faster languages.
But those developers don't know how to code in type free languages. So they attempt to add the types back in.
This of course reduces the software development speeds back to their previous speeds.
This means the whole thing is basically folly.
If you want a real example you can take a look at Turborepo, which in weakly typed Go took 1 developer 3 months to develop and has 20,000 lines of code. The direct port to Rust took a team of developers 14 months to develop and has 80,000 lines of code.
Exact same program but the development costs went up proportionally to the increase in the strength of the type system.
There are plenty of developers out there who have only used static typing and don't understand it comes with massive software development costs compared to it alternatives.
If you are developing a SaaS and you use duck typing, unit tests and micro-services. You will get to market long before your competitors who don't.
Go only has basic types and interfaces to emulate duck typing (structural typing). The type complexity in Go is rather on the low side of things.
Acting like Go is comparable to JS is ridiculous; Go's type system is the only kind of type system needed in Ruby. Rust is a staggering outlier in complexity. And the Turborepo port took a long time specifically because they tried to port one module at a time with C interop between the old and new codebases, which massively slows down development in any language, especially Go. This is just about the most dishonest 'example' you could have picked.
Either that or you are saying 'weakly typed' to mean type inference in `var := value`, in which case (a) Rust has that too and (b) that's not what the debate is about, nobody is against that
Stating that A is an integer isn't much of a issue but once you get a reasonably complex program and A now has a compound type made of 5 parts, it really does slow you down and it really does make you write considerably worse programs for the sake of passing a type checker.
Any commercial code will need to be unit tested so there is no time saving from finding runtime errors earlier and an any good IDE will detect the same errors and provide you with the same auto complete automatically for free without any type annotations at all. These are problems which exist solely in your head.
1 developer vs a whole team of developers. I think you need to face the facts.
There are studies comparing old dynamically types languages against statically type languages. They always show approximately 1/3 of the lines of code being used with 3x faster development times in the dynamically types languages. This isn't some new discovery.
Well even Python is strongly typed but for the sake of this we are discussing type complexity.
It seems to me that this is equivalent to a language without a type checker that automatically generates a unit test for every line of your program that tests its type.
And some types can be inferred by the compiler, as e.g. for new instantiators. Or array, int, str convertors.
In the past couple of decades I have been through a couple IPOs, a couple of acquisitions, and have been in engineering leadership roles and slinging code in half a dozen different shaped eng/dev cultures.
In every case, static typing makes teams faster and gradual typing was a pain with potential payoffs that were muddy. Gradual typing is a shitty bandaid and so are type annotations.
I have migrated no less than 30 systems from various languages to Go across different companies, divisions, and teams. Mostly PHP, ruby, perl, python. Didn't migrate the elixir but I would have if given the opportunity.
In every single case, the team started delivering software faster. Prototypes became faster with the sole exception of prototype admin crud panels which we have needed like twice out of the nearly three dozen services I have worked on migrating. And super dynamic json can be a pain (which I blame not on problem spaces but on less thought out dynamic typed solutions offloading their lack of design onto customers via randomish response bodies).
When programs/applications get larger, the complexity tries to combinatorially expand. It can quickly outgrow what newer team members can juggle in their head. Type systems take some of that away. They also take away tests that are there due to lacking types. "What if this is a string, or list, or number" isn't a question you ask, nor is it a test you write and maintain.
When everything fits in your head, dynamics types are freeing. When it doesn't fit in your head, tooling helps.
Even smaller programs benefit. The dozens of teams I have personally witnessed don't find adding a type as a slowdown - they see whole test cases they can ignore as impossible to compile.
First, YJIT/ZJIT do much better when they know the type signatures of methods. You pay a performance penalty for implicit polymorphism, e.g. using a mix of types (Integer, Symbol, String) etc in a method signature.
Second, from my experience with Typescript, as much as I naturally dislike type declarations, I find it does help LLMs. Having strongly typed libs/gems and being able to mix in untyped app code would be a nice balance.
The running interpreter knows the type of objects. Ruby isn't untyped.
The annotations do nothing for the interpreter.
They still exist at runtime, and people who work on the codebase need to somehow know what to expect. Having a uniform syntax helps to formalize this knowledge and make it machine understandable so it can assist developers by providing quick hits and preventing mixups automatically (saving attention/time for other matters).
Types may be rarely important for local variables, but they matter for API contracts.
IME this is the exception more than the rule. There will be a ton of manipulations where I don't really care what the types are, just whether I can do the specific thing I want on them.
For instance you receive the data from an API and want to pass it to the appropriate validator. The type definitions are noise, and checking them is the validator's job.
Now it's nice to be able to work with stricter types where needed, ideally I'd want to switch that on and off, instead of being stuck with them everywhere.
These type extensions let you get some of the benefits of static typing for projects already written in Python or Ruby.
Or maybe you are an expert with a framework, you are very productive with it, you know the tricks, but you wish it had types support so maintaining these systems would be easier.
Picking a “better” language or learning a framework in another language is not always a pragmatic choice.
Code that doesn't integrate directly with wires (controllers, active record, websocket, etc)
IMO This is for complex, well refactored, testable code that provides a business layer. Coding larger projects like depot management, shipment, order management, middle frequency trading, customs all benefit from types and IDE help. Types basically scale the language beyond just filling in the blanks in your framework. You can get pretty far doing that, but not far enough. That's why all ruby based companies push for type systems. They know the pain of not knowing what to pass, or refactoring code that allows a parameter to be multiple types.
Having used plenty of strongly-typed and dynamically-typed languages, I really can't say strong typing has had any effect on me whatsoever. I honestly couldn't care less about it. I also can't remember ever having a type-related bug in my code. Perhaps I have an easier time remembering what my types are than others do. Who knows?
I write in Kotlin for myself, and Ktor and React or Ktor and Htmx + SolidJS, for web stuff; but those are decisions I made for myself, but I know what it's costing me to not have the raw convenience that is Ruby's Active Admin infrastructure, among other things, I'm sure.
So the reason to add types to python/ruby is that switching to a statically typed language you lose power and expressiveness. But if you use a type-directed linter, you can prevent many of the common errors writing in a dynamic language.
You could use an entirely different language of course, but that involves other changes and compromises.
`def greet(name: String, greeting: String = "Hello"): String`
will work for kwargs with default values — https://type-ruby.github.io/docs/getting-started/understandi...
e.g.
I know it's all subjective but I think that reads better and it's valid ruby.To be honest low-code with a static analysis tool would be my favourite syntax for this.
https://type-ruby.github.io/docs/learn/functions/optional-re...
However, no mention of this basic head scratcher in the docs. :rolling_eyes:
I understand that many programmers come from languages where their brain has been adjusted to necessitate and depend on types. And they get help from the compiler in capturing some errors. But it is the wrong way to think about programs and logic. I'd wish these guys would stop trying to ruin existing languages. Go add types somewhere else please.
Note: I also use java, so I am not against types per se. I am against a want-on need to slap down types onto everything and your Grandma, merely because your brain (of type afficionados) needs them for survival.
I'm not convinced that the time savings of types exist at all, but even if it took twice as long to do anything with types, there is a completely valid argument that "it's worth it to look at nicer code".
In both cases, I'd say you're undercutting your own points by being overly bombastic and harsh towards people with different viewpoints.
You'll engender equally impassioned responses, which won't actually engage with your overall points, but which will instead be mean and catty right back at you. Maybe this is what you want, but I doubt it. There's much more useful discussions to be had on HN.
I wouldn't say it's really a beauty of the language, it may have been the original design intent but time has shown what's actually maintainable.
The reality is that there certainly are enthusiast programmers who can thrive with the lightweight elegance of stock Ruby, but most people writing code professionally aren't enthusiast programmers under ideal conditions. Everything is always a little more distracted, a little less well-defined, and a little more coupled to legacy than anyone would want. And those are the conditions where I want my tools working as hard for me as possible, automatically.
An example I always used to use was something like a method that could take a single item or a collection:
In other words, isn’t describing Crystal as “Ruby with types” similar to describing C++ as “JavaScript with types”?
https://github.com/wouterken/crystalruby
It allows you to call crystallize on a ruby method and then recompile it with crystal and call it over FFI, which is pretty neat.
It would be really cool if this trb syntax could get close to the crystal syntax for method signatures at least.
I'd love to be able to move chucks of hot code to Crystal but leave everything else in ruby for compatibility with existing projects.
But it's not a migration path for Ruby codebases to add types, like the new initiatives for type annotations are. It's just that the syntax used by the available options has been somewhere between bad and downright terrifying until now.
Crystal's intent, as I see it, is very different from Ruby's. Because it compiles down to machine code in a single executable, it's good for making things that are fast and easy to deploy. I've used it to make small web services as well as the bigger thing I mentioned above.
So, you extremely rarely can run Ruby code in Crystal. But simple scripts are trivial to annotate. Larger apps won't require huge changes, but you're likely to run into dependencies you also need to port.
"Language with ruby-like syntax" more appropriate.
I think low_type is a much more elegant solution: https://github.com/low-rb/low_type
I think that static analysis could be done with an extension to rubocop via Prism though. Same for documention features via Ruby-LSP tooling.
I think if they worked on those they would very quickly pick up support as the syntax is quite nice.
I agree with other posters here. I don't need everything typed - Ruby's duck typing is an awesome feature - but I do wish that some of the more important interfaces in our code were more strongly self-documenting and enforced.
The website is quite extensive, but the gem only has ~1.5k downloads. It’s presumably very early on the adoption curve
Oh well.
I'm not saying we (humans) don't need type checkers and I love TypeScript, but something is happening where AI might theoretically surpass the power of traditional type checking. Have the power to catch even more invalid code than the static analysis tools, linting tools, etc.. we have now.
The playground seems broken, I can't get it to report any kind of error. It seems to accept even syntactically incorrect files (e.g. just one unmatched closing parenthesis).
I've seen some mention Crystal as well, but as far as I know, Crystal has nothing to do with Ruby except sharing similar syntax. Their semantics are completely different. It's not Ruby + types.
Otherwise, I think in terms of typed Ruby, this is an incredible undertaking with very well written documentation. Thank you for making this library, I think there's a lot that the Ruby community can benefit from with it. Cheers!
This is an interesting proposal. But for posterity I am going to critique the critique on the website about Sorbet:
Sorbet is Ruby and while it has a DSL that is no different than any other gem providing methods or objects to use. For example you can define a type and assign it to a Ruby constant. Because Sorbet is Ruby.
In general I would say any type system has its own syntax when you go deep into it and need more than this param has this simple primitive type and the method returns this simple primitive type. So you have to learn a DSL and the syntax of a type system.
I think this is a nice way to include types into a project if you like it. I know when you're working on large Ruby projects - 10s of thousands of lines across hundreds of files - types become really, really helpful to figure out what on earth is happening where. In the past I've used DryRb and was pretty happy with it; but an even deeper connection, like this, looks wonderful.
I'd really enjoy it, I think :)
in most of my coding career (rails) i have not needed types. But when i was working on a large codebase with many teams, the lack of types was a recurring issue. now i work in a SOA and face different coupling challenges.
But i much prefer this syntax to what RBS required.
You can't tell anything about an instance variable in ruby if it can be set from anywhere. Of course it's a special case
Dynamic languages have amazing dev speed, but once code matures, slapping some types on that code is just plucking low hanging fruit. It inevitably picks up easy bugs and makes the code better and easier to read and maintain.
Ruby has had no good solution to dynamic typing, for reasons well articulated by the linked piece, but this might just get me interested in Ruby again.
I never tried “typed Lua” variants (such as MoonScript IIRC), but I believe those do require a compilation step.