Then I found out the hard way that none of that works. Basically it's all a lie. You can't use the types in runtime so all that effort you put into the types doesn't actually translate when you want to use the type system to full effect. That was absolutely demoralizing.
For me, the white elephant in the room is that the language doesn't really matter all that much. Good developers will write good code and bad developers will write bad code.
Good developers might use meaningful types and bad developers will use strings, records and numbers everywhere. Guaranteeing a string is passed and not a number is not gonna prevent many bugs. Guaranteeing a `PhoneNumber` is passed can truly prevent bugs. But that's never the code that you actually see in the wild (even in the article).
In the real world, most people can't even use half the type system they claim is so great.
Zod I think is quite popular.
Typescript isn't perfect (sound?) So you can still get errors even if things type check, but if you are disciplined using those libraries instead of `as`, the problems are minimal.
There you have types at runtime. If you really want to be pedantic about it you can use classes and instanceof as well
In fact even Java removes types at runtime for code that uses generics, so often you need to do something like that as well
Types as a static analysis tool is great, types tied to the underlying hardware and memory structures have their values (usually performance benefits). Conflating both together usually leaves you with a very weak (unsafe) type system.
TypeA = number
TypeB = number
const myNumber = someFunctionThatReturnsTypeAorB()
I cannot tell which number I'm dealing with because TS doesn't know that type at runtime. I don't think this is about being pedantic. If the language forces you to change the data structure to allow you to differentiate types at runtime, then it's a very limited type system IMO.If all of this came for free, I wouldn't argue with it. But people tend to disregard all of the cost that comes with it. I know I have lost countless hours simply changing code that already works to make TypeScript happy. If all that is to tell me I shouldn't use a string in a number argument, I don't know if the benefits outweigh the cost.
This isn't really the problem: runtime types would solve the issue, but they're a sledgehammer with all sorts of nasty effects elsewhere. Languages with far stronger type systems than F# still have type erasure: it's actually fairly unusual in that regard.
The core weakness of TS (aside from the fact that its "type" system isn't actually sound) is that it doesn't have type-directed emit: you can't automatically generate safe parsers, for instance, because you can't generate anything. Except enums: why those got a pass is beyond me.
And note the switch from 'only' to 'any'.
Anyway just hypothesising.