Techniques for Annotating Errors in TypeScript
Unlike some languages, TypeScript doesn't employ the throws
syntax that could describe potential errors. There's currently no way to specifically annotate what kind of errors a function might throw:
// This won't work!const getUserFromLocalStorage = (id: string): throws PossibleErrors =>
Transcript
00:00 So, as you've probably found, this is not really possible in TypeScript. There's no kind of like throws syntax in TypeScript where you can describe what an error might or what a function might throw. So we can't say throws possible errors, and then it would magically kind of transfer through to this catch clause.
00:18 As well, the catch clause can't really be annotated. You can't say E is possible errors, and then it would do some sort of checking to make sure that's true. Because if we look at this error, then it should say catch clause variable type annotation must be any or unknown if specified. Grim, grim, grim.
00:36 So of course, we can do something like if E instance of syntax error, and then we'll get some logic that sort of specifies, okay, now we can check E.message. That's good. But of course, all of this burden is on the person using your function, not the actual function itself.
00:54 It would be great if we could capture that inside the function. And we kind of can by using a technique that we've seen before, which is the result type. The result type basically is a discriminated union where we can say if success true, then return the data, otherwise success false. And now we can specify the exact type of error that might have occurred.
01:13 So it could be a syntax error or a DOM exception. And of course, you can have different numbers of these. So you could have, you know, like a type success or type syntax error or type DOM exception to have multiple branches so you could handle each error. And inside here, we're wrapping the whole thing in a try catch. And we're saying if it's a DOM exception, do this.
01:32 If it's a syntax error, do this. Otherwise, we throw and then it gets caught further up. So this sort of gives you, it's obviously a lot more verbose, but it's pretty nice for the person consuming this because it means that you're fairly guaranteed that this function is not going to throw.
01:49 And if it throws, you can handle it in a way that you understand. So yeah, the result type is really the kind of the only way really to handle this kind of errors simply in TypeScript. Otherwise, you're just relying on narrowing things down inside the catch block, which
02:06 is fine too, but there's no way yet of handling or annotating errors that a function throws.