People in glass houses shouldn't throw rocks. People in software development shouldn't throw anything.
TL;DR=throw and raise are fuck ugly anti-patterns. Golang got it right. In typescript, just use type unions with you return type and a custom error type.
Yesterday, my code hit an exception, and I had no idea why. When I went to look at what the cause could be, my eyes started welling up. Not out of pride, but out of disgust (also my screen monitor is painfully bright).
I had a lovely time trying to keep track of all the throw catch statements. My brief stint playing with Golang told me there was a better way. Typescript didn't need to be this hideous (I am a born-again never-nester).
For example
function async makeServiceRequest(url, args): Promise {
// do something interesting, but ultimately
return await axios.post(url, args);
}
Concise. Except oh no, because where is the documentation about what happens if url is wrong or if args cause a 404? It's all embedded in promises, and so that means we either need to start using .then & .catch (please, no), or we have to use try/catch in a caller scope.
Try-catch is the herpes of software. One function catches it and then every function catches it.
Instead, we can just wrap (WINK) the request to axios.post in a single try catch, and modify the function signature a bit:
function async makeServiceRequest(url, args): Promise<Response|Error> {
try {
// do something interesting, but ultimately
return await axios.post(url, args);
} catch (error) {
return // the error, or a better error
}
}
Now the compiler is listening. A caller must confirm the type of makeServiceRequest:
...
const service_request_result = makeServiceRequest(url,args);
if (service_request_result instanceof Error) {
// handle_appropriately
}
...
And life continued without scoping out const's or forcing us to use error: any|unknown.