Throughout my application, I throw custom error objects that need to be caught by the callers while all other exceptions should be rethrown. Hence, I need to check for the type of the exception in most catch blocks. I want to introduce a function like assertMyError in the example below to encapsulate the type checking logic and to make the code more DRY.
class MyError extends Error {
public constructor(public code: string, message?: string) {
super(message)
}
}
/** Rethrow the argument if it is not a `MyError` instance. */
function assertMyError(e: unknown) {
if (!(e instanceof MyError)) {
throw e
}
}
try {
// This call may throw `MyError`
downloadFile("hello")
} catch (e) {
assertMyError(e)
// Error 2571: Object is of type 'unknown'.
console.log(e.code)
}
However, TypeScript does not play along. Despite the fact that the control flow only continues beyond assertMyError if its argument is a MyError object, TypeScript will not let me use it as such. Is it possible to annotate the signature of assertMyError such that I will be able to use its argument as a MyError after it returns?
I am aware of type predicated functions in the style of function f(arg: unknown): arg is Class. However, these functions return a boolean that I would need to check in an additional if-clause which I sought to eliminate the condition within the catch block with this design in the first place—the error needs to be thrown anyways.