Objects 16 exercises

Dynamic Keys with Index Signatures and Record Types

First, let's check out the errors we're getting:

const scores = {};
scores.math = 95; // red squiggly line under math
scores.english = 90; // red squiggly line under english
scores.science = 85; // red squiggly line under science

Hovering over math shows us the error:

Loading solution


00:00 Okay, let's investigate these errors. First of all, property math does not exist on type empty object here. Okay, that's interesting. Well scores if we hover over it is being interpreted as an empty object. Okay, so we need to find a different sort of type for it. Let's first

00:17 of all, just grab out a type here. And let's say scores here is going to be just an empty object. And let's just say scores is scores, this will give us a good starting point. So now in this empty object, we need to basically say any key that we add to this object, the value of that key is going to be a number. And we could obviously like do it, you know,

00:37 math is going to be number here. And now the math error goes away. Same with English is going to be number as well. And same there. But what if we want to add a dynamic key? Well, we can add what's called an index signature to this type. And we can say, let's just call

00:54 it subjects. And we'll say that's a string. And then we give the value of that index. So we can say this is a number. So we use these square brackets inside here, kind of like you would if you were adding like a dynamic key inside here. So conscore equals like this,

01:11 you would say score, and then add something there. So in this case, this would have to be a number now. So this is the same kind of syntax, except we are also adding a type annotation there to say, this is the type that this index should be. So you can think of those syntaxes as kind of the same. So now we've got subjects. And we can call this

01:29 anything we want to, by the way, index, but let's call it subjects. It's a string. This has to be either a string, a number or a symbol too. And you can see though, if I say number here, then scores.math, it doesn't exist on TypeScores. Whereas if we were to do scores.0,

01:47 then it would work. So interesting. So by saying, subject string, we can say, okay, the only properties on here can be strings. Although that rule gets broken in a couple of different ways because of the weird way that JavaScript handles object keys. But then we can say, okay, this one is a number. If we try to add a second one onto here, for

02:05 instance, saying this is a string, it's not gonna let us because there can only be one index signature per object type. So there we go. So this is a duplicate. Actually, if we were to say number here, I think this might work. It's not assignable to string index. Yeah, you can see that multiple index signatures are a little bit dodgy and don't

02:23 particularly work too well. So this is the first way of doing it. The second way of doing it is to use an interface. We can use exactly the same setup as we had before, except on an interface here. Very nice. Then we can even declare it in line too. So this is just an object literal. So we just say, okay, declare the index signature in line. And then what's

02:42 the fourth way? This is gonna surprise me. Oh yeah, we can use a helper type for this. The helper type is called record. And what record does is it basically says, okay, basically, if you look at the definition for record here, it's kind of like an index signature. It's

02:59 slightly different, but it basically acts like an index signature. And so what it says, we are creating a record where the keys are string and the values are number. If we were to change this to Boolean instead, then each of these would be incorrect until we passed

03:15 in the Booleans here. So there's no particular advantage over index signature versus record. I would say record is really nice because it's just a repeatable pattern. The syntax is kind of easier to understand. You're using an abstraction instead of using the lower

03:30 level thing, which is quite nice. And yeah, I'd say record is what I would reach for first, but I wouldn't blame you if you go for index signatures either. So this is index signatures in TypeScript.