Check out a free preview of the full Making TypeScript Stick course:
The "Thrown Values as unknown" Lesson is part of the full, Making TypeScript Stick course featured in this preview video. Here's what you'd learn in this lesson:

Mike discusses how thrown values used to be considered type any but now can be chosen to be regarded as type unknown. The useUnknownInCatchVariables compilerOption allows any error found in a catch block to be labeled as type unknown automatically.

Get Unlimited Access Now

Transcript from the "Thrown Values as unknown" Lesson

[00:00:00]
>> Another straight up win, thrown values can now be regarded as unknowns. So before TypeScript 4.0, anything you would encounter in a catch block cart value, it would be of type any. And this has always made giving me a little eye twitch, right? Dealing with thrown values in a consistent way is important because errors are nice and throwing things that are not errors can leave you missing information.

[00:00:36] So here's an example. If you just in your terminal run node -e, which is, I believe, evaluate or execute. It'll run whatever string you pass it as if it's code. So here's an example of throwing an error. And you can see we get this nice little stack trace.

[00:00:54] Here is an example of us doing the same thing and throwing a string. Note the lack of a stack trace. And you may say, well, I always throw errors, what monster would throw string in their code? Surely not me. And you may be perfectly consistent about that in your own code.

[00:01:16] But even a smallish JavaScript or TypeScript project these days has thousands of dependencies and you cannot be sure what exactly is thrown behind the scenes. And it only takes a couple of these errors without stack traces to start making, it's basically robbing you of the clues you need to fix bugs that occur when users are actually hitting code paths that we'll throw, right?

[00:01:48] So how does this relate to the type of the error? Well, it encourages us to check these values out and to see is this really an instance of an error? Or is it something else, right? So, for example, in this case where we're throwing a string, the proper thing to do here would be to say, this isn't an error, something weird is going on here.

[00:02:09] Let's pass the string into a new error and throw that. So at least we get a stack trace to where this was caught. And that's better than nothing, that's better than complete mystery here, which is just sort of an error occurred somewhere in your application at some time.

[00:02:29] Good luck, have fun. That's what this situation tells you. So here's what the first aspect of this feature set looks like. You can now do this. You can say, I'm catching a thrown value here. Please type it as unknown. You could not do this in earlier versions of TypeScript.

[00:02:53] And you can see here we rethrow where appropriate. We take anything else, and we kind of just coerce it to string, and throw it as an error. So everything above this point in our code, we'll get something with a message property, a stack trace, right? All of the things that they are important clues to help us track down the problem.

[00:03:20] So this is great. This helps us do the right thing. In addition to that, so this I think landed in TypeScript 4.1 maybe. Shortly after we got a compiler option that allowed us to say throughout our entire code base, don't even make me do this. I want you to just say anything I find in a catch block is an unknown always.

[00:03:45] And that will encourage you to use type guards and to handle it as appropriate. And this will help make sure that at least in the code that you write, you're gonna end up with the clues you need to play detective later on. I am unaware of any downside here other than its you will uncover things in your code and you will need to patch them up.

[00:04:14] But this is a straight improvement with no negative consequence as far as I'm concerned.