The Weird Parts of TypeScript 13 exercises
explainer

Object.keys and Object.entries in TypeScript

Here we'll continue from where we left off with the User interface and users array:


interface User {
id: number;
name: string;
}
const users = [
{
name: "Waqas",
},
{
name: "Zain",
},
];

When we map over our users and add an id to them, we add an age propert

Loading explainer

Transcript

00:00 We're going to start where we left off in our previous exercise, where we have an interface user which has ID number and name string. And when we're mapping over our users, adding an ID to them, we're accidentally adding an age property as well. Now you might think, or rather, I've been saying that TypeScript doesn't care about these differences

00:19 or it doesn't automatically check the access properties because that won't cause any issues at runtime. Now there's, it might actually cause an issue at runtime if you're using some sort of like, if you're mapping over those keys to use them in some sort of behavior. So if you look at this, if we say, okay, users with IDs dot map,

00:39 and we say we have our user in here. Now, if we follow the flow of this, we have a type here, which is going to be user, which has ID and name on it, but it's actually got a third property on it. It's got a property of age, which is not being expected. So you might think that this keys that we returned from object dot keys,

00:58 it should probably be like, if TypeScript was really smart about it, it would say that is an array containing either ID and name, but it's not. TypeScript, because it doesn't do these access property checks in all places, it basically says object dot keys. Okay. We can't be sure that it has all of the right properties on here.

01:18 It can't be sure that this is an array of ID and name. And so keys is just typed as an array of strings. This is slightly annoying because this means then that when we say user and we just pass in, let's say we just grab the first key. So keys zero,

01:34 and this is probably going to be like ID. So const, actually it's going to be named. So const name key is this, and it's not actually going to let us index into it with a key that we know exists on object dot keys. Very, very annoying. So this,

01:53 even though we know that this name key is like probably going to be named, given the sequence of events that we've seen above, TypeScript doesn't let us do this. And the reason it's doing that is because it wants to be really conservative with the way that it handles object types, because it knows that pretty much users without IDs, there could be a bunch of different stuff in here.

02:14 There could be like 12 is going to be 46. And like this could just be anything. And so it doesn't, it's not sure that it wants to handle this on the type level. It can't say definitively that other object keys aren't present on objects that are being passed around. So object dot keys,

02:34 this means that this is loose, essentially loosely typed. And object dot entries is also, well, loosely typed, I think is the wrong phrase. I think this is the strongest type that TypeScript can properly provide in this situation. And if we have entries here, you can see that object dot entries,

02:53 we have an array of string and any array it looks like here. If we were to for each of these, we have, let me grab this out. We have a key and value here, and we can see that the key is just string. And then the value is going to be any in this situation.

03:13 So this is pretty like unintuitive to people when they first see this and they think, Oh, TypeScript, object dot keys. Maybe they've just got that wrong. That doesn't seem right at all. Whereas if you understand that TypeScript doesn't deal in precise object types, it only handles like it lets you pass excess properties all over the place.

03:31 Then the looseness or the perceived looseness of object dot keys and object dot entries will start to feel like it makes a bit more sense. And hopefully this, like the problem of iterating over objects is still there. And we're going to look at that in a future exercise.