4 ms·
yet another reason I try and avoid throwing/rejecting promises in typescript code and just return `Thing | Error` everywhere. I'm sure there's something fancier
by macrael 4y ago
yet another reason I try and avoid throwing/rejecting promises in typescript code and just return `Thing | Error` everywhere. I'm sure there's something fancier I could get out of using a full Result type but this gets me a compiler enforcing I handle all errors somehow and keeps `try catch` out of my business logic.
- candiddevmike 4y agoHuh, never thought to do this. Coming from Go, this would honestly be very ergonomic (not being snarky).
- kansface 4y agoJS let’s you throw any type as an error.
- hot_gril 4y agoWell you know what they say, the better name for Go would've been Errlang.
- macrael 4y agoIt's honestly great. I also have done a fair amount of go (and before that a decent amount of objc) and it feels in the same vein as both of those but with some nice additional compiler helpers.
- rickstanley 4y agoI do it the "go" way, with: type Result<K = any, T extends Error = Error> = [K, null] | [null, T]; And use it: const [response, error] = await tryFetch<Type>(""); if (error) { handle(); }
- macrael 4y agoBut this way you are losing the type checker yelling at you if you try and use response without having handled error. What I like about res = something(): Thing | Error is I have to do if (res instanceof Error) { handle() return res } doSomethingWith(res) or else the compiler will yell at me for trying to doSomethingWith(Error)
- rickstanley 4y agoI see. Well, for what it's worth, in my tuple example, you either have one or the other, i. e. the K result or an Error; so, if you don't check for error (or result), the compiler gives an error saying that "K is possibly `null`". Example: https://tsplay.dev/w2p0Vm https://tsplay.dev/w2p0Vm
- macrael 4y agothat makes sense, and I like the simplicity of `if (err)`. I'm sure it's uncommon but you still lose the compiler check if the function can return null as a matter of course.
- tluyben2 4y agoThis is what we do; for me it came from ancient times when I was doing fulltime C dev and I mostly kept it up (but improved) except when working on teams that want or already have exceptions all over in all layers.
- hot_gril 4y agoThat's ok, and I get the purity of only using the response instead of an implicit exception, but it gets repetitive when nearly every func is potentially returning an error. You only have to handle exceptions at the outermost layer. I don't understand why this is seen as a "gotcha" in the article, it's the whole point of exceptions.
- 9dev 4y agoUsing exceptions would be a lot easier however if typescript picked up the throws and would warn about missing catch blocks, just as every other language with exceptions seems to get right…
- hot_gril 4y agoIf your function doesn't handle an exception, it throws it. If TS required you to say `throws` every time like in Java, that'd be repetitive like explicitly returning `| Exception`. Maybe it could detect if you're not catching in the outer event loop. Idk though, I just use vanilla JS and don't find these safeguards necessary. Worst case, if I fail to handle something, my NodeJS express server will handle it by sending back a 500.
- 9dev 4y agoYeah, but I would want to know which library function could possibly throw an error and not be caught off guard by that after deploying to prod :-/
- hot_gril 4y agoIt's almost accurate to assume that everything can throw an error in high-level code like this, especially in something complex enough to warrant a lib. The thing is, in a webserver, those are all unexpected errors and thus 500. There are only a few known ways the client can use it wrong, and I give 400 for those.
- macrael 4y ago