Explicit exceptions - a solution to fragile code dealing with exceptions

Alright, I think I'm understanding your vision better. We declare which exception types a particular function might throw. Anything not in its signature will automatically be escalated. Then, every time we call one of these exception-throwing functions, we use a try-catch, and explicitly indicate how we would deal with each type of exception (will we handle it? propagate it? escalate it?)

I can see that being able to solve the problems just as much as my original proposal, as long as a try-catch is used every time an exception-throwing function is called. In order for this try-catch concept to fully work, we would need to expose some easy way for the user to escalate the exception (as they can't just do it by simply omitting the exception from the excepts clause like in my original proposal). So, something like this:

function getUserProperty(userId, propName) throws 'NotFound' {
  try {
    return getUser(userId)[propName]
  } catch 'NotFound' (ex) {
    throw ex // propagate this exception
  } catch 'SomethingElse' (ex) {
    throw Error.fromException(ex) // Escalate the exception.
  }
}

This, unfortunately, can only be enforced to a degree by a linter. Code like this would cause issues:

function doSomething(fn) {
  fn() // Is a try-catch required here? Or not?
}

For the discussion on adding new syntax for exception handling, the error catching pipe operator "|^" that we've been discussing in this thread along with the pattern matching proposal would make for a really elagent solution:

function getUserProperty(userId, propName) throws 'NotFound' {
  const user = getUser(userId) |^ match(?) {
    // Propagates NotFound
    when({ code: 'NotFound', ..._ }) { throw ? }
    // Escalates any other exception
    else if (? instanceof Exception) { throw Error.fromException(?) }
    // Let all other fatal errors pass through
    else { throw ? }
  }
  return user[propName]
}
1 Like