I guess a "cold shower" is that it only checks the type. You could put 999 into a variable that's supposed to hold the outside temperature.
An interesting implementation of this idea is outlined here too: https://medium.com/iterators/to-tag-a-type-88dc344bb66c
A strictly newtype can be very powerful, but needing to "unwrap" your datatype to use it in normal operations of that datatype can be a little unwieldy so tagged types are a pretty interesting mechanism that provides type safety and convenience. I don't think it's strictly better though, it depends heavily on context.
A function that has a parameter of ints but will only yield numbers within a certain range? I guess I'm really confused by the Scala example you posted but really trying to understand.
[1] https://doc.rust-lang.org/std/convert/trait.TryFrom.html
I've never done this, but you could also define types for stuff like this. type: PositiveInteger, or type: BoundedTemperature that would only ever hold valid values.
Or one thing where it might come in handy would be when dealing with user/potentially malicious input - SanitizedString etc.
type OutsideTempC is digits 3 range -100.0 .. 70.0;
(Edit: others mentioned this)
``` type Temperature<min: number, max: number> = { x: number | x >= min && x <= max } ```
This is what gets me about “even modern relatively-low-boilerplate type systems just slow me down” folks. That means you’re skipping documentation you ought to be doing.