Best practices for typesafe error handling
What are your best practices for error handling using typescript? Are you throwing (custom?) errors or do you return success/error union types? Or do you do something else?
11 Replies
Unknown Userā¢2y ago
Message Not Public
Sign In & Join Server To View
Thanks for your insights. I'm not sure if I'm a fan of custom error classes in a typescript world where more and more libraries do a functional approach. Creating multiple classes with different fields seems tedious in contrast to defining some union types which could be implemented as discriminating unions. That's why I'm asking for best practices. I can't find any good resources on this topic š
Unknown Userā¢2y ago
Message Not Public
Sign In & Join Server To View
I've seen nevertrow and have thought about using it for our team. What's your opinion on it after using it?
I throw custom errors, we used to heavily use monads and error return types in the past but in js it just makes it more complicated
Mainly because third party libraries and tools either throw errors or expect you to throw errors
And onboarding new people and explaining that you have three different ways of handling errors just makes it tough
So we opted to use async await everywhere and try catch
I once went ham on fp-ts and use monads for everything just to avoid having to use a try catch statement.
The result - spent more time writing flawless code instead of creating value
Thankfully this was just for a personal project.
Thanks for your insights, that's really helpful. But it seems like there is no definitive answer to this (like a best practice) and we'll have to see whats best for us.
It's really hard to find good resources on this topic.
Interestingly trpc returns an error object and doesn't throw an error you have to catch. It seems the topic is handled really inconsistently in the ts-ecosystem.
š¤ correct me and give feedback if I'm wrong š
still new to typescript
This is just because tools like react query return data, isLoading and error objects. You can opt into using suspense which will also result in throwing errors to be caught by an error boundary
Thank you I'll have to take another look at that. š
A few things to add to this if you're making custom errors:
- You'll want to take advantage of the
cause
property in the second parameter of the Error
constructor to wrap the original error. This will preserve the original stack trace.
- Be sure to set the prototype properly with Object.setPrototypeOf(this, MyCustomError.prototype)
. This will allow you to use if (error instanceof MyCustomError)
Here is an example of using the above: