Estus Flask
Estus Flask

Reputation: 223144

Narrowing down error type in catch

For this piece of code

try {
  throw new CustomError();
}
catch (err) {
  console.log(err.aPropThatDoesNotExistInCustomError);
}

err is any and doesn't trigger type errors. How can it be narrowed down to the type that error is expected to be?

Upvotes: 67

Views: 64417

Answers (1)

jcalz
jcalz

Reputation: 330246

You need to perform a check yourself to narrow inside a catch block. The compiler does not know or believe that err will definitely be a CustomError:

try {
  throw new CustomError();
}
catch (err) {
  console.log('bing');
  if (err instanceof CustomError) {
    console.log(err.aPropThatIndeedExistsInCustomError); //works
    console.log(err.aPropThatDoesNotExistInCustomError); //error as expected
  } else {
    console.log(err); // this could still happen
  }
}

For example, here's my evil implementation of CustomError:

class CustomError extends Error {
  constructor() {
    super()
    throw new Error('Not so fast!');  // The evil part is here
  }
  aPropThatIndeedExistsInCustomError: string;
}

In this case err will not be a CustomError. I know, that's probably not going to happen, but the point is that the compiler won't do this narrowing automatically for you. If you are absolutely sure of the type, you can assign to another variable:

try {
  throw new CustomError();
}
catch (_err) {
  const err: CustomError = _err;
  console.log(err.aPropThatDoesNotExistInCustomError); // errors as desired
}

but remember that you could possibly run into trouble at runtime if you're mistaken about the type.

Good luck!

P.S.: See TypeScript issues #8677 and #9999 for more information.

Upvotes: 82

Related Questions