How do you js/typescript wizards catch multiple types of exceptions since there are (still) no type annotations on catch clauses? #js #typescript
@jorisvaesen Something like: isNativeError(error) ? error.message : typeof error === ‘string’ ? error: ‘unknown’ and you put that in a function like describeError or whatever you like or a function that logs it the way you like. Depending on how you handle exceptions.

@airtwee
But what if you would take different actions based on the exception type?

Like handling an ApiException differently than a TypeError, for example.

I'm really curious if all devs create their own handling system which seems so off to me for something standard as exception handling.

@jorisvaesen then I write an typecheck function isApiError(error: unknown): error is ApiError. However I do not use this often, but it can come in handy. To differentiate between more as two error types never happend to me yet, so a simple if is mostly sufficient

@jorisvaesen You'd use type predicates in the catch statement to sort out what kind of exception you're looking at.

Type predicates (formerly guards) are predicate functions that take in a value of a broad type, and return the result of a boolean expression, but have a special return type that assures the caller the input value is of a specific type.

This only works in TypeScript.

https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates

Documentation - Narrowing

Understand how TypeScript uses JavaScript knowledge to reduce the amount of type syntax in your projects.

@unshittifier
Interesting approach. But this is just a fancy if type check, or am I missing something?

@jorisvaesen
You're not missing anything, welcome to #TypeScript lol

The type check will coerce future references of the checked value to the type the predicate checks for, which is nice for development but not much else.

@unshittifier
So a fancy if with type checking and casting basically. At least the type checking is reusable that way.

Aren't there any popular packages who tackle this problem? I'm currently using vue3 but can't seem to find anything broadly used. Guessing every dev builds their own system, which is a shame for such standard behavior.

@jorisvaesen I think this is where there's a difference in paradigm between PHP and the JavaScript ecosystem.

PHP and other OOP languages that lurk on the backend in my experience tend to prefer elegantly handling a crash whereas JavaScript and everything built on top of it avoids raising exceptions as much as possible.

Likely this is a result of how exceptions are handled i.e. well in PHP and poorly in JavaScript. There is probably someone more well-versed who has a better explanation.

@unshittifier
Seems like a logical explanation. Although, I still find it strange that there are no widely used packages for this problem.

I've put something together using the visitors pattern which could work for me as an OOP developer 🙂

This way its reusable and more readable than endless if-s.

https://github.com/jorisvaesen/ts-error-handling

GitHub - jorisvaesen/ts-error-handling: Trying to overcome the lack of type annotations in catch clauses

Trying to overcome the lack of type annotations in catch clauses - GitHub - jorisvaesen/ts-error-handling: Trying to overcome the lack of type annotations in catch clauses

GitHub

@jorisvaesen Interesting approach, though I'm not sure that's better than the alternative.

Consider this TS Playground with type predicates: https://www.typescriptlang.org/play?ts=5.1.6#code/JYWwDg9gTgLgBAbzgQQB7AgZwKJStOAXzgDN8Q4ByAQ3S0oG4BYAKFYGMIA7TeYTNBhx4CAXjgAKAKYAuOAFcuAay4QA7lwCUcqXH4o6w-FDiiAfHF3AeMal3ZSIJA0NzHmbFjCgBPRKzhAuAB6YLgAOkjWQg5qGHYAC0lZBWVVDU1-FiC9Zwl+QSw3aGlNTIQAnKDOHggAGylwqREoCQADABIERpApTExqAHMpYgkuxt44+Uw4AH5Zy3DOABNdeapKQk02zQ8cmJYDoA

versus how your code (naively) compiles: https://www.typescriptlang.org/play?ts=5.1.6#code/JYWwDg9gTgLgBAbwIIA9gQM4FEpWgXzgDM8Q4AiAQzU3IG4BYAKGcoCMMYpKBjeHgDaUMGODjxQAEpQB2AEwEBTKImbM4GuGACubAcB5weEGZyja+0ABTrNdsHhiK+iuXCiLKckwICeRygEBNl4AawAuOAAxbRk+dBlbDQBKRHw1JntdfUMAc0UYAGFA4LCrZMiYuJgE1Uy7TQ8YbSgZOBgAC2AMADoeEpCeUMZ6jXSWUbh2M154AEdtQOAiXytlCUjY0JkIAHcZCrg2CAglWRHx5kFhUVR0bFxoaXklFUUUJ3lRcSfZBWU6lk9AY4Aslis1o8oJsZNs9gdIsdTp42ggkg0mi02utoHBgKYYLIeIoIEQ4HdMD8oCM7JdJjpgYZOJQankCgBZRQiSj5KKkKmQjbkmgPCSHMz43KAhoaTGtOA4qA9EBcjA8xRwADUcAA5HArHrtYLoD1mc1RAB+C0KqF9CByDVW3U61Lal06mmacZ064iOAAZS4kqpz3+bw+ii+Yihode0o0DJyoMW+ghiphcP2hyRZ1R6LscraMF8YBJZMVcAAvNXdRKZLkPei6UCk2aQTwPCzFAB1YCdAAiiiIlG0AhgACFFB1KAA3dBQcqRQNQYMxv5xtGTAsFLFwGSKXYBoP1kPr5RWY3QqYyXypSsAPnjMs0xlMyJ6AgguUvU1EddyySejK+DJE2zA+kIfqni8ygAIraIoCF1OiDjADOXbuJ43gyH4cDTjBUAYJE0FhgA2gAuiMKGOM4ThuK+ZgWDA1ipJuz7tF0vT4WGoiVnAFFAXAzaaImIJtoYHaeE4i7RhIsZwQhCHomxz6FnuB4cd05SCcJCbZCCXhyFY3GvMRa4EYcJGvPBiEaipMqdN0PQmcovQ6BgHTGWeUCARk7FqY5GA6X5In6RJLI8J56ZwFsOz7AANBxeC7AA8jI7LdBgkqIicuZVu05iKIcM4QMAbj2Q0RC4lYDHwC5KikppXHeRgrH5s+yz6vVPRgqmqyKskbVbuxmjdfkRQDGUySXr5EwjapO6tIJ7HjCtIUyp1VidMlaUZSIkpDfNGjbXsNoSMtXpgUwdJcP4FUAPT3UY9oap0LIBEWHTJQqKDEmANQmBg4EBDAkX6tFsXwodmhWQptl9J20mgcNGg9IZVj7oeFKir8BEXtFsi3lWj4VexDHvoqVjY7DSrjZy3K8vyUI-sIwr3FSg0XWMg3taj6PLqucneQjUk9n2HSDsOo4TlOs7zuUyPsX0EVRVCiVcAhs34EAA

Maybe there's promise here, but I don't think an OOP approach is particularly elegant for the problem you want to solve.

Things that stand out are having to cast the error to fetch the message. And using type predicates to branch into the correct handler.

Personaly I'd find it preferable to make a library of common predicate-handler pairs that you could use instead of reinventing if-else chains or switch statements.

https://www.typescriptlang.org/play?ts=5.1.6&ssl=25&ssc=2&pln=1&pc=1#code/JYWwDg9gTgLgBAbwIIA9gQM4FEpWnAQwzgBVV1tdoBfOAMzxDgCIC1NmBuAWACg+AxhAB2GeABEApnQIBXADYwceKHAC8iPnG1wAjrILzgdAJ4AuOAApJF2cIDWwiAHdhASguS4wYsvxqAPjgvYFEYAmEBSQg6OD8oABotHQALCIATeRsrbPi3dSChUQgsgDpJKihrUpBJDAwCAHNJNyTeah5+XiKxOHJMePVNXh09AyNTC2tbBydXD2DvYjJ2ShUCxdCxCKiY0n616DbRtOFM7On91byNnpLJcsrLAAMAEgQH2vqmyVpLd4e2xgsmIAH5QcFSkJ0l5wXAAOTw6huZ6tPjUPh8GBQEzDUYAenxcFKJPRcAEBBgAhSOUqM0cLnceJ0xisB3ipX0hmMJmslTc+QQyVG2nZlVKp3OfJUbk6owxIx0knkGBCsUsUhkCiU4q5E15FRlguFIs1ckUHMlWWl0FlJoVo2VquZIrgMBSeGcwUqnDghLgditknSbpMYEk9vRQA

But this doesn't read well compared to statements like:

if (isErrorType(error)) { /* handling code */ }

TS Playground - An online editor for exploring TypeScript and JavaScript

The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.