How to assert the type of an argument of a function upon successful return?

Viewed 25

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.

0 Answers
Related