/proposal-catch-guards

TC39 proposal for catch guards

Primary LanguageHTMLMIT LicenseMIT

ECMAScript Catch Guards

This proposal adds catch guards to the language, enabling developers to catch exceptions only when they match a specific class or classes.

This proposal complements the pattern matching proposal and does not try to compete with it.

This proposal draws heavily from similar features available in Java, C#, Ruby, and Python.

Status

Champions: Guilherme Hermeto (Netflix, @ghermeto), Mary Marchini (Netflix @mmarkini)

Stage: 0

Lastest update: draft created

Motivation

  • Developer ergonomics:

    Today, developers have to catch all Errors, add a if or switch statement and rethrow even when they want to catch one particular type of error:

    class ConflictError extends Error {}
    
    try {
      something();
    } catch (err) {
      if (err instanceOf ConflictError) {
        // handle it...
      }
      throw err;
    }
  • Parity with other languages:

    Scoping error handling to specific types is a common construct in several programming languges, as: Java, C#, Ruby, and Python.

  • Code/Engine Optimization:

    Engines will be able to skip completelly the blocks if the error doesn't matches the correct type.

Syntax

Option 1 (using as):

class ConflictError extends Error {}
class NotFoundError extends Error {}
class OtherError extends Error {}
  
try {
  something();
} catch (ConflictError as conflict) {
  // handle it one way...
} catch(NotFoundError | OtherError as other) {
  // handle the other way...
} catch (err) {
  // catch all...
}

or:

class ConflictError extends Error {}
class NotFoundError extends Error {}
class OtherError extends Error {}
  
try {
  something();
} catch (^ConflictError as conflict) {
  // handle it one way...
} catch(^NotFoundError | ^OtherError as other) {
  // handle the other way...
} catch (err) {
  // catch all...
}

Option 2 (using if instanceOf):

class ConflictError extends Error {}
class NotFoundError extends Error {}
class OtherError extends Error {}
  
try {
  something();
} catch (conflict if instanceOf ConflictError) {
  // handle it one way...
} catch(other if instanceOf NotFoundError | OtherError) {
  // handle the other way...
} catch (err) {
  // catch all...
}

Option 3 (using :):

class ConflictError extends Error {}
class NotFoundError extends Error {}
class OtherError extends Error {}
  
try {
  something();
} catch (conflict: ConflictError) {
  // handle it one way...
} catch(other: NotFoundError | OtherError) {
  // handle the other way...
} catch (err) {
  // catch all...
}

Implementations

  • Babel Plugin //TBD

Q&A

What if the error is an string?

We are trying to solve for types only, so this would work:

try {
  something();
} catch (String as err) {
  // handle it...
}

But it would catch all errors thrown as strings. Hopefully the pattern matching proposal will address the use-case of matching regular expressions.