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 Option and Either types. (Either instead of Result because 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 like TaskEither which roughly serve the purpose of a Promise but with an explicit error type.
Now that you mention it, must-use detection for Either values 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.