It was pointed out in #9999 that catch
variables never get narrowed because they're of type any
, and you can't change their type because they're not allowed to have type annotations.
This leads to pitfalls like
try {
// do something
} catch(e) {
if(e instanceof MyError) {
console.log(e.filname); // oops.
}
}
Proposal: allow type annotations on catch variables as long as the annotated type is exactly any
or { }
(we can't reasonably make this an implicit any according to --noImplicitAny
so that behavior would be unchanged). But now "safer" developers can write
try {
// do something
} catch(e: { }) {
if(e instanceof MyError) {
console.log(e.filname); // error, property not found
}
console.log(e.filename); // error, forgot to narrow with a guard
}
Alternatively (or in addition to), we could just let catch
variables get narrowed despite being any
, but this would be a fairly odd carve-out.
:balloon: :tada: 10,000th issue :tada: :balloon:
Related discussion in #8677
we could just let catch variables get narrowed despite being
any
, but this would be a fairly odd carve-out.
You could also see it the other way, that type guards were originally intended to work everywhere, but #1433 created a special carve-out where type guards no longer work (for pragmatic reasons). In that light, having type guards still work in the catch
clause, despite the any
type, is actually reducing the existing carve out.
A consideration here is discoverability. The following gives no compiler errors, so the author may mistakenly believe that TypeScript is type-checking the code when it is actually not:
try {
foo();
}
catch (ex) {
if (ex instanceof FooError) {
/* recover from FooError */
ex.foo // NOT typechecked - won't find typos, won't be picked up in refactorings
...
}
else {
throw ex;
}
}
It seems a bit magical and arbitrary that if we take the same code, but change catch (ex)
to either catch (ex: any)
or catch (ex: {})
, then it _also_ compiles without errors but now provides additional type checking.
How would a user know that they need to add the annotation if the compiler doesn't complain either way? Often people don't realise there is something wrong with their code until they see a compile-time or runtime error, and with TypeScript the main benefit is to get more of the former and less of the latter.
This will be handled be #9999
Most helpful comment
:balloon: :tada: 10,000th issue :tada: :balloon: