Headshot of Marius Schulz
Marius Schulz Front End Engineer

TypeScript 2.5: Optional catch Binding

TypeScript 2.5 implemented the optional catch binding proposal, which changes the ECMAScript grammar to allow for the omission of the variable binding within a catch clause. That is, you can now omit the error variable and its surrounding parentheses in a try/catch statement:

try {
  // ...
} catch {
  // ...
}

Previously, you'd have to always declare the variable even if you weren't using it:

try {
  // ...
} catch (error) {
  // ...
}

The Emitted JavaScript Code

If you target an ECMAScript version that doesn't support optional catch binding (such as ES5 or ES2015), the TypeScript compiler will add a variable binding to each catch clause that doesn't have one so that the generated code ends up being syntactically valid.

Here's our try/catch statement from before again:

try {
  // ...
} catch {
  // ...
}

And here's the JavaScript code that the TypeScript compiler emits when we target ES5:

try {
    // ...
}
catch (_a) {
    // ...
}

If we were to compile our code with --target esnext instead, a catch clause without a variable binding would be emitted unchanged:

try {
    // ...
}
catch {
    // ...
}

The Official ECMAScript Proposal

At the time of writing in late January 2018, the official ECMAScript proposal is at stage 3 of the TC39 process. Since optional catch binding isn't part of the final feature set of ECMAScript 2018, it's highly likely to be standardized as part of ECMAScript 2019.

The good news is that thanks to TypeScript, we can use optional catch binding today without having to wait for all relevant JavaScript engines to catch up with the implementation.

Use Cases for Optional catch Binding

You usually don't want to silently ignore errors in your applications. At least, you'll typically want to log them to the console. However, in some rare situations, you might not need the variable binding after all.

Let's say you're trying to log an error to the console and then, for some reason, the logging code itself causes another error. You don't want your logging code to throw an error, so in that case, a catch clause without a binding might make sense:

function log(error) {
  try {
    console.error(error);
  } catch {
    // There's not much more we can do
  }
}

I encourage you to read Axel Rauschmayer's blog post about optional catch binding for a more comprehensive list of practical use cases.

This post is part of the TypeScript Evolution series:

  1. TypeScript 2.0: Non-Nullable Types
  2. TypeScript 2.0: Control Flow Based Type Analysis
  3. TypeScript 2.0: Acquiring Type Declaration Files
  4. TypeScript 2.0: Read-Only Properties
  5. TypeScript 2.0: Tagged Union Types
  6. TypeScript 2.0: More Literal Types
  7. TypeScript 2.0: The never Type
  8. TypeScript 2.0: Built-In Type Declarations
  9. TypeScript 2.1: async/await for ES3/ES5
  10. TypeScript 2.1: External Helpers Library
  11. TypeScript 2.1: Object Rest and Spread
  12. TypeScript 2.1: keyof and Lookup Types
  13. TypeScript 2.1: Mapped Types
  14. TypeScript 2.1: Improved Inference for Literal Types
  15. TypeScript 2.1: Literal Type Widening
  16. TypeScript 2.1: Untyped Imports
  17. TypeScript 2.2: The object Type
  18. TypeScript 2.2: Dotted Properties and String Index Signatures
  19. TypeScript 2.2: Null-Checking for Expression Operands
  20. TypeScript 2.2: Mixin Classes
  21. TypeScript 2.3: Generic Parameter Defaults
  22. TypeScript 2.3: The --strict Compiler Option
  23. TypeScript 2.3: Type-Checking JavaScript Files with --checkJs
  24. TypeScript 2.3: Downlevel Iteration for ES3/ES5
  25. TypeScript 2.4: String Enums
  26. TypeScript 2.4: Weak Type Detection
  27. TypeScript 2.4: Spelling Correction
  28. TypeScript 2.4: Dynamic import() Expressions
  29. TypeScript 2.5: Optional catch Binding
  30. TypeScript 2.6: JSX Fragment Syntax
  31. TypeScript 2.7: Numeric Separators
  32. TypeScript 2.7: Strict Property Initialization
  33. TypeScript 2.8: Per-File JSX Factories
  34. TypeScript 2.8: Conditional Types
  35. TypeScript 2.8: Mapped Type Modifiers