These kinds of struggles with JavaScript and TypeScript are part of why I moved to Rust. I value the sanity checks the compiler provides: warning when a
Resultis ignored and refusing to compile when amatchon anenumis missing a branch.Also, in Rust,
Resultis for recoverable failures, whilepanic!is generally reserved for bugs, broken internal assumptions, or cases where the program has reached a state that it believed should be impossible.Yeah, in most languages
panic-type operations are relatively expensive compared to return-compare operations, and most languages recommend not using throw as a common-case branching pattern when testing return values is available. You usually don’t want throw/catch to be called in a tight loop.I’m using Rust on the server, Typescript on the client. Some very interesting options have appeared in Typescript over time for better ADT handling!
ts-pattern provides a match function that verifies matches are exhaustive. Yes, it’s a static check. It’s got a powerful matching language that does stuff like extract nested properties from complex inputs, like Rust’s match. I recommend reading the documentation - for me it led to some “I didn’t know that was possible!” moments.
I’ve also been using fp-ts to get
OptionandEithertypes. (Eitherinstead ofResultbecause fp-ts is inspired by Haskell.) It has features for processing fallible values as monads which gets close to the conciseness of Rust’s?operator and try Trait, but is more generalized. It also has mtl-ish types likeTaskEitherwhich roughly serve the purpose of a Promise but with an explicit error type.Now that you mention it, must-use detection for
Eithervalues would be helpful. Eslint has a built-in check that does exactly that for Javascript’s native Promise type. I haven’t tried it, but it looks like eslint-plugin-fp-ts has a rule that might do the same for other types.





