Errors 10 exercises
solution

Options for Indexing Without Errors

We have an error because we are attempting to index into the productPrices object with a string.

Here's the error message:


Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ Apple: number; Banana: number; Orange: number; }'.

Loading solution

Transcript

00:00 Okay, let's work out why this error is occurring here. Now, the key here is you can ignore the element implicitly has an any type. What this is basically saying is element implicitly has an any type. I don't know what this type is supposed to be. Okay, that's essentially what this phrase means.

00:17 Expression of type string can't be used to index type apple banana number. Now, if we think about what indexing something means, it basically means accessing it with dot notation, right? Or with this dynamic string notation. So apple banana orange, these are the three things

00:36 that you can use to index into product prices here. Now, we could make this error go away because we know that we're passing in product name string here. So the thing we're trying to index into product prices is a string. So it could be pair, for instance. It could be something that doesn't exist

00:55 on these product prices. And we know this because we can do get price pair like this and the error is not going to be caused here. So the error has to be caused somewhere because there's a mismatch with what we're trying to index into product prices with between what its keys actually are. So how do we resolve this?

01:14 No index signature with a parameter of type string was found on type apple banana orange. So index signature, what does that mean? Well, if we think about this product prices here, we can index into it with only three possible values, apple banana or orange.

01:31 Those three values are kind of like its index signature. The signature is kind of like, you know, the way it describes the way it can be called. So it's like, you can only index into me with three possible keys. So we can though, we could make that index signature potentially wider.

01:48 We could say you could index into it with any string. So you could say product prices is now a record of, don't know why I went American there, a record of string number here. Now what's going on here is we're now saying that product prices, it can contain any string.

02:07 So it has an index signature of string. This means that when I access it, I can actually pass in anything into here and I'm going to get back a number or I can pass apple if I want to, or I can pass pear and that might return me a number or undefined. So now the error goes away because we've given an index signature

02:26 to this product prices, or we've said it's index signature instead of being just apple, banana, orange is now any string. So we take this off here. How can we make it though? Let's say that we didn't want it to error here. We didn't want it to error on return product prices product name. We actually wanted it to error

02:43 when we call the function with the wrong thing. Let's say we wanted to change product name. So it's actually apple, banana, or orange. We could of course do this. We could say orange or apple or banana. And now I've got to add an extra pipe there. Now the error goes away because we're indexing into it

03:04 with the correct things here. If we were to add pear onto this, then we're going to get an error here because property pear does not exist on apple, banana, orange. There you go. So we're starting to see why this error exists. So now we get an error here because pear is not assignable to the closer type that we were given here.

03:24 Nice. So this is one way of doing it. We can even remove this duplication. We can say type of, or rather key of, type of product prices. And now if we add an extra product price to this, so we say get, whoops, get price. We get apple, banana, or orange here.

03:44 And let's say we remove orange from up here. We're then going to get sort of the same error down here because we no longer have an orange on the product prices. This means the key of those product prices is not going to include orange. And so get price doesn't have orange on there. And nice, this is one way of doing it too.

04:03 But what if we know, we actually do know the product name is going to be apple, or banana, or orange. And we kind of want to cheat TypeScript a little bit. We want to get rid of this error properly. Well, what we can do is we can say product prices, product name. We can basically cast product name to the thing that we want it to be.

04:22 And we can say as key of type of product prices. And now the error goes away. If I move this into a separate line, we can say const index into this, and we can just use index there. So now we can see that index is basically apple, or banana, or orange.

04:41 And this means then that product prices index, we've basically forced it into that slot. We can still call get price with something that isn't that. We can say get price pair, for instance. And this means that we will possibly get some unsafe stuff coming out of here. But it does mean that you've made the error go away,

04:59 which is sometimes all you really want to do. So those are your three options. To review, we can do product name here. We can basically make get price, force it to be either apple, banana, or orange. Or we can widen the product prices. This is often the safest route, I think, to make it so that you can add any kind of thing

05:18 to product prices and index into it in any way. Or we can use a cast when we actually index into it and force it to be that thing. So three choices I would, in general, where you can widen out the type. This will make your apps, I think, a little bit more maintainable. And yeah, it sort of just makes more sense with what you're actually doing in TypeScript.