That'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.
It's all tradeoffs. For me, not having to deal with passing state past a trailing try/catch clause and not worrying about errors potentially bubbling out of one layer into another are worth the extra "if (res instanceof Error) { return res }" lines
The trouble with throwing is that the compiler doesn't care if you catch. For any library that throws, I wrap that up in my adaptor layer with try catch and then return an Error upwards. That way in the rest of my domain I've got the compiler complaining if I'm not handling an error that is coming from below. I can be sure that when I'm handling an error it's not going to be something random from 2 layers down, because it was explicitly returned by the layer I'm calling.
As in most things coding, you can accomplish the same thing with either approach, but I believe by returning an `| Error` there's a better chance for the compiler to catch a bug before I run the code.
Using 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…
If 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.
It'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.