Maybe I am misreading you but for example, in Swift, marking a function as “throws” makes it a compiler error to not handle the error, and makes it an error to not throw an error or return in the function. In Typescript, the error in a catch handler is of type unknown. I don’t see how it could be any worse than basically untyped errors AND unpredictable runtime errors without reading the docs or implementation. At least you would get some compiler help.
Here’s an example of why it would be worse to have poor error type coverage:
function libFoo(foo: string): throws FooError;
function libBar(bar: number): boolean;
Both of these functions throw. With untyped errors, you have to assume that this is at least a possibility. Now you have every reason to assume it’s safe to call one of them without handling errors.
The argument as I understand it, which is convincing, is that types like this are inevitable if typed errors were to be introduced. The scope of even well typed code with no documentation of even the errors thrown directly is enormous. The scope of code which might propagate errors from calls deeper in its stack is unimaginable. And there is basically no way to do static analysis to meaningfully reduce that space.
It could be fair to say this was a missed opportunity earlier in TypeScript’s development. But introducing typed errors retroactively would lead, trivially, to millions of cases like the above. Many in very hard to find ways.
Could those types be produced and refined to be as high quality as existing types (first party or community provided)? Of course. But it would take years. And unlike introducing types where none exist, the gradual story just doesn’t exist. You’d have to treat literally every function and property access as `throws any` to get safety equivalent to the gradual types story for non-errors.
And the incentive to type one’s own code with errors is hard to imagine: how can I, as a library author, say with any confidence what anything I write throws, if I have no idea what the underlying code throws (or if it really even does)? Why would I take on the maintenance burden of getting it wrong? Or incomplete? Or incomplete and wrong?