TypeScript Fundamentals Challenge 4: Solution
This course has been updated! We now recommend you take the TypeScript Fundamentals, v3 course.
Transcript from the "Challenge 4: Solution" Lesson
>> Mike North: Welcome back, we're going to go through the solution to the functional shopping cart exercise. We're gonna run our MPM test, functional cart, no, sorry, it's just cart, no, it's cashier, isn't it?
>> Mike North: Yes cashier, failure of a bunch of tests as the world is before we do any work.
[00:00:25] So we'll open up our exercises folder, and look at the cashier exercise and open up this type script file. So we've got a function here, and it's doing nothing at all of interest. And so our job is to make it so that this pass some of this test.
[00:00:46] We can start at the beginning, so whatever this cashier function returns should have something on it and called add, and that thing better be a function. But first, we were given a couple interfaces.
>> Mike North: And I'm gonna define an interface for the thing that this returns, right? So cashier should return a cashier API.
>> Mike North: So surely it should have an add on it.
>> Mike North: And let's actually just look at the exercise here, so length and total, we can add those first.
>> Mike North: I wonder if I can copy that whole thing.
>> Mike North: Nope wishful thinking, so length is a number.
>> Mike North: Total is a number, add is going to take a cart item and return a cart API.
>> Mike North: I may have misspelt that. I called that a cart API. I may as well keep it consistent.
>> Mike North: Okay so that's add, sorry if I'm flipping back and forth, my mistake. I'm gonna change that to add item, and then add is gonna take basically the deconstructed cart item, name, price, and quantity and also return of CartAPI.
[00:02:25] So, this will be addItem, and then we'll have add(name: string, price, number, qty: number)
>> Mike North: And now we need this CartItem.
>> Mike North: Name: string; price: number; qty: is gonna be number; okay.
>> Mike North: So now we've sort of moved. We've got an appropriate error here that's saying, we can't assign an empty object literal to the type cart API, and that is cuz we are missing a bunch of important things.
[00:03:17] So we need
>> Mike North: Length of, we will just say 0 for now.
>> Mike North: 0 for now. And we'll have a function here add(name, price, qty, and we'll have the default value be set to 1.
>> Mike North: And what's the problem here? Return it zero, zero add item, so we need to return a CartAPI.
>> Mike North: Okay, now it's quieting down. So we've stated our intent to return this CartAPI. And so once we do this, you can see that these are the complaints that are left.
[00:04:28] So we'll have an items array here. And because we're using typescript, we can put a type constraint on this array. We're not allowed to put anything into it, unless it matches the structure that we refer to as CartItem. Only things matching that structure can be pushed in. And so in this situation, addItem and again like, because we have stated, we return a CartAPI.
[00:04:53] This is what we're returning. You'll note that like all of the type information I have, it's already taken care of because of that interface, right? This is TypeScript trying to give me benefit of the doubt that it's found a way to make what I'm returning conform to CartAPI, just by applying inferred types to various things.
>> Mike North: So we're gonna do that, and then return this. And then, we can do that. Similar thing here, we're gonna push, name, price, quantity, and return this.
>> Mike North: So we're passing some more tests here. We've passed ten, still failing nine, and looks like many of them have to do with length and total.
[00:05:53] Adding a few items by chaining, maybe that has something to do with the total as well. So obviously we haven't done anything there. What we're gonna do is our new knowledge of the way getters work. So these become accessors, right? We can consume them as if they're properties, but you can see they're sort of functions.
[00:06:22] They're accessor based properties, not value based properties.
>> Mike North: And, that's not right. Get length.
>> Mike North: Read only length. Okay, so we can do that, that's fine.
>> Mike North: See if that'll make it happy, nope. I know, we're not even calculating that correctly. We were meant to not even hit this little snag, cuz I haven't talked about read only, or access modifier keywords anything like that.
[00:07:08] So length is not just the number of items in the array, but it is we have to count the quantities up. And we can do that any time we're trying to derive a singular value from an array. There's a higher order function we can use. Does anyone know what that is?
>> Speaker 2: Reduce.
>> Mike North: Reduce, so we could say items reduce and the reducer is gonna take two arguments and an accumulator, and the current item. It's our job to implement that. And we'll start counting from 0. This is the initial value of that accumulator, so note that even in the reducer.
>> Mike North: We can get rid of this down here.
>> Mike North: Let me cause it to, let me make it shut up a little bit with the errors.
>> Mike North: So here, the reducer is, it has type imitations built into it, but let's see if we can figure out what's wrong.
[00:08:21] Can someone read this and figure out why this reduce is complaining to us, as it currently stands?
>> Mike North: Someone who knows what reduce is?
>> Speaker 2: You're not returning.
>> Mike North: I'm not returning. The initial value I've given it of 0, it's basically saying, okay well that's a number. And so as a result, we see that right up at the top says acc: number.
[00:08:47] It says, well now I can give this to you with a type of number and you'll also, this reduce rate better return the type of number. Because that's gonna be the new value of the reducer, the next time we turn over in this reduced function. So a lot of great type information working for us, and it's busted us on not returning like we should be.
[00:09:05] This is it saying, I expect the function of this specific shape. And you have given me something different and therefore fix it. So if we were the assembly say return 1, it will go quiet. That's how exactly what are those complaining about. In this case, we are gonna say return the current value of the total plus the quantity of whatever item we're looking at.
[00:09:31] So it's gonna just sum these items up via quantity.
>> Mike North: So now we can do something similar with total, and in this case we're gonna say the total is it's another reduced function. But it's quantity times cart item price. And at this point I expect we're passing all our tests, and we are.
[00:10:01] So what we're seeing here, first off, is that we can use getters just as we would use value-based properties, right? So we have satisfied, even though we're doing something like this, it still satisfies this part of the interface up here, right? Those line up just fine. So getters work just fine.
[00:10:31] And also, when we're working with higher order functions especially like in this case, it seems that whatever type we pass in that kinda dictates another type, right? There is a relationship between these things. For example, if I were to write this in quotes, this is gonna be complaining because
>> Mike North: It's a read only, sorry, it takes a little while to decode these messages here.
>> Mike North: Just know, see callback just below line 11 on the right side, see where it says callback fn previous value colon string? That's basically saying, okay, well now your accumulator is a string.
[00:11:18] So I'm gonna pass you this as a string and you better return a string. So it's almost like there's a relationship between types that are use for various parameters here, and that leads us up to our next topic, which is generics, that is how this is defined, right?
[00:11:35] As soon as we do this, you'll see that the reduce function has this U. See how it says reduce and then angle brackets number, so we're operating in a mode where we're going to return a number, the initial value of the accumulator had better be a number, and therefore our call back numbers first argument needs also to be a number.
[00:12:27] A really nice constraint to have. Let me make sure I'm passing the tests, and I am, okay.