Skip to the content.

Errors

There are multiple strategies how to handle an error.

It is always performed by try-catch statement.

Remember: Async function invoking will throw rejected value. It can be captured by try-catch

Read more at MDN

With a recent introduction of unknown type in a ‘catch’ block, value whould be first checked to be an error: if (e instanceof Error) { ... }

Catch all

function throwError() {
  try {
    throw new Error("My Error");
  } catch (e: unknown) {
    console.log(e);
  }
}
throwError();

open code in online editor

Re-throwing errors

In some cases you can expect some error, perform an action and throw the same error to be processed on higher levels.

function reThrow() {
  try {
    throw new Error("My Error");
  } catch (e: unknown) {
    console.log(`Error happened: ${e}`);
    throw e;
  }
}
reThrow();

open code in online editor

Catching only subset

You can filter out only necessary errors in catch using instanceof

function filterErrorInstanceOf() {
  try {
    throw new TypeError("Bad Type");
  } catch (e) {
    if (e instanceof TypeError) {
      console.log(`Expected type error: ${e}`);
    } else if (e instanceof RangeError) {
      console.log(`Expected range error: ${e}`);
    } else {
      // re-throw all others
      throw e;
    }
  }
}
filterErrorInstanceOf();

open code in online editor

Or as variation use switch case:

function filterErrorSwitch() {
  try {
    throw new TypeError("Bad Type");
  } catch (e: unknown) {
    if (e instanceof Error) {
      switch (e.constructor) {
        case TypeError:
        case RangeError:
          console.log(`Expected error: ${e}`);
          break;
        default:
          throw e;
      }
    }
  }
}
filterErrorSwitch();

open code in online editor

Use finally

finally is called each time after try or catch been called, regardless of thrown exceptions

function errorFinally() {
  try {
    throw new TypeError("Bad Type");
  } catch (e) {
    if (e instanceof TypeError) {
      console.log(`Expected type error: ${e}`);
      throw e;
    }
  } finally {
    console.log("I will be called always");
  }
}
errorFinally();

Custom Errors

Custom errors can be thrown as well. To be able to do it, just extend Error class, and throw newly created instance.

Remember: Do not throw anything except Error or it’s subclasses

class InvalidInputError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "InvalidInputError";
    this.stack = `${this.message}\n${new Error().stack}`;
  }
}
const invalidValue = 100;
try {
  if (invalidValue > 0) {
    throw new InvalidInputError("Some field is not valid");
  }
} catch (e: unknown) {
  if (e instanceof Error) {
    console.log(e.name); // InvalidInputError
    console.log(e.message); // Some field is not valid
    console.log(e.stack);
    // Some field is not valid
    // Error
    //    at new InvalidInputError (...)
    //    at eval (...)
    console.log(`Error happened: ${e}`); // Error happened: InvalidInputError: Some field is not valid
  }
}

open code in online editor