Hacker News new | ask | show | jobs
by status_quo69 2496 days ago
> It feels like people are lulling themselves into a false sense of security by making increasingly complex self-consistence schemes via type utilities, but they just shrug when I point out that the foundation of the scheme is still unsound.

I don't agree with this premise. Assembly is an untyped language but you can build things on top of it like Rust or Haskell, or you can write in C and cast everything to a void. I do* agree that validating the types of values is a hard problem in any language and that JSON.parse should be typed as `unknown` these days (although there are also reasons why it should not do that due to casting), but it makes complete sense IMO. JSON.parse could return any valid JSON value. The compiler doesn't know the structure of the string provided beforehand.

1 comments

The difference between something like Rust->ASM and TS->JS is that the former actually emits runtime machine code to deal with e.g. an Option, whereas in TS, the compiler is happy to emit the exact same runtime code for both `const o: Foo = JSON.parse('null')` and `const o: Foo | null = JSON.parse('null')` without throwing a compile error.

Rust makes it exceptionally "hard" to write unsafe code, by making it blindingly obvious when you're doing it, whereas in TS it can be very challenging to spot unsoundness, especially considering that the audience of the language is not type system scholars.

I won't argue that getting strong code in TS is easy but I definitely don't think it's as hard as you're making it out to be. That being said, it's more of a limitation of the underlying execution context in my opinion, and you have to realize that it's not just jS that's out to get you but the whole ecosystem. But that's the expectation in all languages, even in Rust. In production optimizations all bets are off and you're on your own if your app dies.

For example of what I mean by the platform being out to get you, the second parameter to JSON.parse is a recovery function. So it'll happily parse anything and return anything. Again, should be "unknown" but it was typed before unknown was a thing.

    JSON.parse('{ "fooDate": 123456789 }', (key, value) => !key.includes('Date') ? value : new Date(value));

    JSON.parse('123456789', (key, value) => new Date(value))
I actually just learned about this today, since I was doing some digging. Horrifying stuff for a typed language to get around. FWIW, we've made it an explicit lint error to use the `any` type, and enabled --noImplicitAny and --noImplicitReturns. That's been pretty solid for our codebase and because I/O is limited to a few edges, we can call out those edges for type guards.