any vs unknown vs never: TypeScript demystified

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let's take a look at three types in typescript that are often kind of confusing for people any unknown and never let's Jump Right In and talk about any any is probably the simplest of these three types and that's because it really just disables any type checking on the values that we assign the type any to in our example here you can see that we're creating this vowel variable and we're assigning it the type of any and after we do that we can treat it as many different types of values we can treat it as a number we could treat it as a string we could treat it as an array or as a function we could treat it as just an object here or as a date and notice that in all of these cases typescript is not throwing any errors it's not telling us that we're operating on this value in an invalid way instead it's just letting us do it so any just disables type checking for those values it's the ultimate way to say I know better than the typescript compiler about the way these values can be handled I hope it's obvious when you look at this code that this is really a bad idea there's very few cases where any is a smart choice one of the big ones that comes to mind is maybe you're porting a JavaScript library or project to typescript and you're going to need to use any a little bit maybe until you fill out the types for all of your existing values any will allow you to start using typescript but not have to completely move over to typescript before you can start shipping your application again so any is useful there but in almost any other case where you want to use any you probably want unknown and we'll look at unknown next one last problem with any or maybe this is just another perspective on the same problem is that if you think about the typescript type system in terms of set theory any doesn't really fit in you might think about any initially as the set of all possible values but the truth is there's no operation that you can perform on all possible values for example I can't do a increment or a two uppercase on all possible values those only work on a subset of values and so the fact that typescript lets me perform all of these actions on a value of type any just means the types have been disabled and not that we're still acting within the type system so if you do want the set of all possible values in typescript what's the correct type for that well this is where we move on to unknown I'm going to replace our any here with the word unknown and now our value here is of type unknown and notice that now we do have type checking that makes sense our value here is some value from the set of all possible typescript values and there isn't anything in that set that allows you to perform all of these operations and so you can see we're getting some errors so how should we use the unknown type well the first thing to keep in mind is that in many places where you're using any you probably want to use unknown instead I've written my fair share of functions that accepted on any argument because I thought well I really could accept any argument here but really I want unknown I don't want to disable the type checking I just want to say all possible values are accepted one simple example would be a logging function or any kind of telemetry where you want to be able to accept any kind of value and then you're going to process it accordingly but how exactly does that processing happen we can look at it in our example here so we know we have some value here we don't know what type it is because it could be anything how can we start forming these operations well the key to using an unknown value is to narrow it to a particular type so for example if I think that vowel might be a number I can simply do a type check to say is the type of valid number and if it is now I can properly increment that number notice that outside of the if block here the type of our vowel is unknown but inside of our if block here the type of vowel is a number we've now narrowed from the set of all possible values down to the set of numbers and we can actually do that increment of course we can do the same thing for our string example we can check to see if this is a string and if it is then we can successfully uppercase it we could do the same thing down here check to see if this is an array and then we can map over it of course we'll never be able to use Val as both an array and a function and so that error is just going to have to stay narrowing the type of vowel enough so that we can do val.fubar equals two takes a bit more work than you might think first we have to check that this is a truthy value so it's not null or undefined and then we need to check that it's an object then we need to check that it has a property named Fubar and then finally we have to check that the type type of that property is a number before we can assign to it but if all of those things are true then at least we know that we can do vowel.fubar equals true and if we hover over it here we can see what typescript now knows about our value it knows that it's an object and it has at least a foobar field I'm curious about why it says unknown here instead of number I would have expected because we're actually validating here that velv.fubar is number anyway at least it does allow us to assign a number so that's an interesting one and of course for the last one here we can check to see if Val is an instance of date and if so we can pass it to our function that takes a date The key thing to keep in mind here though is when you have an unknown value you can narrow it down to unexpected value and work on it from there so unknown is the set of all possible values but what about the set of no possible values this is where never comes in never is the empty set in typescript there is no possible value that you can assign to the type of never so what good is a type that can have no values assigned to it well there's actually a couple of interesting things that you can do with never never ever can be handy when you're building out your own complex types there are plenty of times where I've built out a complex type in typescript only to realize at the end that it resolves to never and therefore I can't actually use it and usually this just means I have a typo or maybe I did an intersection where I meant to do a union that type of thing here's a simple example of how this might work we're trying to create two types here one is the intersection of number and string one is the intersection of Boolean and null and as you can see if we hover over this here both of these evaluate to never because you can't have something that is both a number and a string you can't have something that is a Boolean and also null there are other situations though in your actual code where never can be incredibly useful and one of my favorite patterns here is the exhaustive switch and I think we've talked about this before on this channel but here's a simple example of how this works let's say we have a union here of user types standard user or an admin user and of course we got a login function and we've got a switch statement here that's going to operate on our different user types the the default case here is where we can validate that we have handled all of our users and we can use never to do this we're creating this unreachable variable the type is never and we can actually assign user here to this type what this means is that user must already be never because if user has some type other than never it's impossible for us to say here is a type that is in the empty set the set that has no types now the real place where this shines is if we add a new user type here maybe say we have a super admin or something like that now our code does not compile we have an error and if we hover over our error here we can see that type string is not assignable to type never what is Type string now how is user type string well if we hover over user we can see that now user is super admin it's not even type User it's narrowed just to the super admin part and that's because we've passed our two cases here where it's standard or it's admin and so we know that in this block user has to be super admin and we can't say that that is a never type the solution here of course first is to add our super admin case here this solves our problem because now we've exhausted all possible values of user right user here is a very narrow type it has three values in this set and so if we know none of those three values are in the set then user must be never there's nothing left in the set to check and so we have another empty set and so the type of user now being an empty set it matches never which is also an empty set so that's a quick look at the any unknown and never types in typescript I find the set theory perspective on typescript to be an incredibly helpful way to understand some of the nuances about how the typescript type system works so I'm going to include a couple of links in the description below to articles that have helped me understand that better so definitely check those out if you enjoyed this video please consider clicking the like button and subscribing that's super helpful for me thank you so much for watching and I'll see you in the next one
Info
Channel: Andrew Burgess
Views: 21,164
Rating: undefined out of 5
Keywords:
Id: kWmUNChlzVw
Channel Id: undefined
Length: 8min 0sec (480 seconds)
Published: Mon Feb 20 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.