Any vs Unknown Overview0:00
In this lesson, we're going to cover the difference between the any type and the unknown type. So both of these types are very similar in that you use them when you want to accept any kind of data, but there is a very important distinction between the two. In our previous lesson, we looked at this logger function, which takes any variable and we typed it as unknown, and it just logs it to the console. So that allows us to do things like this. We can call logger and we can log a string. We can also log some arbitrary object. And if we run this, we should see those log out. So we get Laracast rules and we also log out the object there. Let me just copy and paste this so we can show some differences. Let me type this as any, and let's just comment this out.
Runtime Error with Any0:42
Let me just copy and paste this so we can show some differences. Let me type this as any, and let's just comment this out. Now, again, this is going to work just as it did before. Now, let's imagine we decide to adapt this logger function over time. So we wanted to do something like we want to log something to uppercase, right? So this function now basically takes something and logs the uppercase version of it. Now, obviously, this will only work for a string. So here we're calling logger with a string, and that's not throwing an error. But here underneath where we're calling logger with an object, we would expect this to throw an error because we're trying to pass it a type.
But here underneath where we're calling logger with an object, we would expect this to throw an error because we're trying to pass it a type that does not have the toUpperCase method on it. So if I run this now, I'm going to get an error. So I get a runtime error, something.toUpperCase is not a function. Any essentially tells TypeScript to turn off the type checker. You're essentially just saying TypeScript, don't inspect this at all. Just ignore this. Whereas if we were to change this to unknown type, we would get a TypeScript error here.
Why Prefer Unknown3:35
which means we're still going to have type safety in our code, even though this function can take whatever it wants. So I can run this and it's going to work as expected. So that is the key difference between any and unknown. And it's a very important difference to understand. You should, especially for a new project, you should never use any anywhere in your code. You should always use unknown. If you're migrating an existing code base, sometimes it can be easier to use any,
If you're migrating an existing code base, sometimes it can be easier to use any, and I would still urge you to make sure that you absolutely need to use it before you put it anywhere in your code base. Using even a single any in your code introduces room for error. We saw, if I change this back to any, you're essentially allowing a part of your code to allow all kinds of bugs in without being picked up by the type checker. And you're doing all this work to add beautiful types to your code to make it safe to get static checking.
And you're doing all this work to add beautiful types to your code to make it safe to get static checking. And you're adding failure points in your code and undoing all that work. So use any very sparingly. I try and never use it. Let's look at an example of one of these cases where unknown does actually get a bit trickier than this function here. So I'm just going to comment this out. And now let's look at some object types. Object types are a bit more tricky.
Any in Object Types4:46
And now let's look at some object types. Object types are a bit more tricky. So here I'm going to use this type alias keyword that we've seen before. We're going to cover this in more detail in a later lesson, but basically just creating a type called AnyType, which is an object with two props. And both of those props have type any. So we have this anyFoo, which isn't of any type, has propOne and propTwo, as we declared in the type up here. The first property is going to be a string.
has propOne and propTwo, as we declared in the type up here. The first property is going to be a string. The second property is going to be an object. So this satisfies the any type because the props can be anything. We're essentially not doing type checking. So now I can do a console.log and I can access this any foo.propTwo. So, so far, so good. But anything past propTwo, we've completely turned off the type checker. We can just access whatever we want here. We can continuously chain any number of things here.
Unknown Objects and Narrowing5:58
So now that we've seen that, let's go to an unknown type. So now we take the exact same structure, object with two properties, propOne and propTwo, but we've changed the anys to unknowns. And we create the exact same object, hello and fooBar, but now it's an unknown type. So now if we want to console.log this out, let me just paste this here. So if we want to log out unknownFoo.propTwo, which exists and the foo property. So we know this exists. We're going to get a TypeScript error, basically saying that the object is of type unknown.
But as soon as we want to access anything off an unknown type or call some built-in prototype method on any unknown type, it's going to throw a type error. We need to narrow that down. And that's exactly what we do here. So to do this exactly like in our type narrowing example before with a string, we do the exact same thing with an object. It's a little bit more complicated. So let's walk through what we need to do first. We need to check that propTwo is defined because unknown could actually accept a type of undefined. So change this to undefined,
Type Casting DOM Elements9:48
but only use it when you need to. Just one last thing I want to touch on is type casting again. So we can also use type casting even without an unknown type where we happen to know more information about the object than TypeScript does. So let's say we're on the front end somewhere. We have an element in our document that has an ID of myCanvas, and we know it's a canvas element because we create it there manually. It's not some external bit of information into our system. It's something we've explicitly created in our code somewhere. So if we click through to this getElementById,
It's something we've explicitly created in our code somewhere. So if we click through to this getElementById, getElementById takes a string and it returns a HTML element or null. So we should be able to read this type definition now based on the lessons we've covered and HTML element. We can click through to that. It has a whole heap of properties on it, but HTML element is a fairly broad type. If we know this is actually a canvas element, we can do something like this. This will implicitly type this. So let's just inspect the canvas element.
