Transcript from the "Index Signatures" Lesson
>> All right, let's talk a little bit about index signatures. So, and I like to start with a motivating use case here. We have a hash or an object that contains a variety of different phone numbers. We have home, we have work, and we have fax. Let's imagine the app we're building.
[00:00:18] And this is the data for the app. We have an address book application where you can have multiple phone numbers. Some of these we know the name of, like home phone number, maybe you have a predefined slot for that. But perhaps you allow arbitrary phone numbers to be added and you can choose whatever label you want.
[00:00:35] So there are some fixed things that we expect to be there. But we want the capability to sort of add other things of a similar shape to this phones object. So an index signature lets us do just that. And I'm just gonna comment this out real quick, and we'll put it all together in a moment.
[00:01:02] So what we're saying, so here's the syntax for an index signature. In fact, I'm gonna make a even simpler version of it up here. So what we're saying here is that we have an arbitrary property key, which is a string. So that's this part in the square brackets.
[00:01:34] And its value is a string. So we could do, You could do that. But you couldn't do this. Cuz it's saying, Look, I want a string. You're giving me a number I want a string. We've built something kind of like a dictionary here a little bit. An index signature is necessary in order to define a dictionary right?
[00:01:57] Meaning a dictionary would be something that it's a data structure that allows you to hold arbitrary values each listed under a particular key. So, if we put this together. We can grab this type just like that, get rid of that. Let's put it up here next to phones, and now we can see, We could have phones.home and look at that, country, area and number, we do this fax.
[00:02:38] And there it is. You could also do custom1. Now nowhere have I defined a field like a property called custom1, but the index signature allows me to do this. You can actually combine this with known properties. So if we were to do this I'm gonna grab this type here.
[00:03:00] And let's say we always have mobile. We always have a mobile number. Actually, I'm gonna change this. No, I'll change the value here. Well, let's examine this error first. So what we're seeing is mobile is missing in type, and then it lists the type of the value on the right-hand side of equals.
[00:03:29] It's like what we're initializing this to. And it's saying, but it's required in type, and then it lists the explicit type declaration. How do I know which is which? Well, here's the word mobile. And it's nowhere in this type. There's home, work, and fax, but no mobile. And so if we were to go down here, And change that to mobile, now look what we get.
[00:03:55] Well, there's a mobile, a known property there, but just as well, we can do work, and there it is. So you can have an index signature on top of explicitly defined fields and they both work. Now a convention I like to use when I'm dealing with something like an index signature, I will, and there are some great TypeScript compiler settings that will enforce this.
[00:04:24] When I'm reaching for a known property, I will use dot notation. When I'm reaching into a dictionary. I will do something like this, just to make it super clear. We'll talk more about those compiler settings later but it's unchecked indexed access. And that would also that would account for the work phone number being potentially undefined.
[00:04:51] I mean, it's here when we initialize it, but I can also reach for like this like. Right And we know that nothing's there for aaaaa, right? There is no phone number here, but TypeScript's acting like there is, because that's what our index signature says is possible. So you kind of wanna do something like this just to allow for the possibility that it might not be there.
[00:05:24] But again this compiler setting which is no unchecked index access, if you went into your TS config, it would convert this for you. It would make sure that you you kind of stick to this convention .notation for known properties, square bracket notation for index field access, Gitano asks, can we do the string or mobile?
[00:05:50] I mean we could, we'll talk more about like union and intersection types, which is what this is. When we say String or mobile, we're really just saying string. It could be the specific string mobile, or it could be any string at all. Well, we're kind of back to any string at all.
[00:06:12] It's almost like a multiply by zero thing. Mobile just sort of falls away, cuz it's it is a subtype of string, so you end up with just string Yeah, LJ asks in chat, why would we have square bracket notation? Why would we have index fields when they're not easily accessible using .notation?
[00:06:35] LJ, really it's a data modeling need. Sometimes you have a need to define a dictionary like this. So at Stripe for example, in our API you would see things like currencies represented using an object where you might see USD and then a number and then JPY for Japanese yen and then a number or something representing a currency amount.
[00:07:05] And you might have a bunch of these, and you want to be able to reference them by a name, right? As opposed to like an array of objects and searching, ffilter for the one with type equals JPY, right? That's, it doesn't really add any value. And there's no value in ordering them, which is what an array is all about.
[00:07:23] There's some positioning implication there that's not meaningful. So sometimes it makes sense to model things this way, but you need to be prepared for a variety of different keys and values to be present. It's really just a different collection type. Ilka asks, how do we tackle JSON types that come with an API call?
[00:07:46] We'll talk a little bit about that later. And in particular, you should check out my full-stack TypeScript course, where we actually have strongly-typed contracts between frontend and backend. Yeah, Enrique, you're mentioning unknown type, that's part of it, but also type guards that help you get from unknown type down to something more useful.