Check out a free preview of the full Visual Studio Code course

The "Challenge 3: Solution" Lesson is part of the full, Visual Studio Code course featured in this preview video. Here's what you'd learn in this lesson:

Mike walks through the solution to Challenge 3.


Transcript from the "Challenge 3: Solution" Lesson

>> Mike North: And let's proceed to the next topic. And let's proceed to the next topic. Once we start sort of unraveling this, we'll see that we kind of have to sort of fix some other things. But essentially, we should only end up adding comments here and we should in the end have some assurance around the various types of things that can be passed in due functions within this piece of code.

>> Mike North: So just to show you what we started out with here, I went to my compiler configuration, my type script compiler configuration, and I added these two lines here, check JavaScript. Otherwise, it would just work with our type script files. It would ignore all of the JavaScript and then no implicit any.

We're saying, do not tolerate ImplicitAny anymore, just bust us whenever you can't figure something out. And now it's our job to go in and to be either explicit about the any type or to maybe define something that's not the Any type. Usually it's the latter that you're interested in.

So with that, let's jump in. I'm gonna start with the listener support module here. And let's proceed to the next topic. So we start from the bottom up, in general. Okay so, the parameter listener has an implicit any type. And that error actually is happening in two places.

And then this payload has an any type. So up here, at the top of this module, I'm going to define a new type. And we're gonna say that this is one of the listeners we're gonna register. And it's gonna be a function that receives as an argument an object.

That covers an array, by the way. An array is a special flavor of JavaScript object. So it's a function that receives an object and it returns a void, that means it returns nothing. I'm gonna actually opt for the arrow syntax like this function that takes an object as a single argument, and it returns nothing.

It would be like it returns undefined, right? And we'll call this a listener. Now we can go down to these areas here and say, I'm going to take in a param of type listener in this last argument here, that's sort of the name of the parameter. So that's basically to say it's this one here, it would have more, would mean more if we took multiple arguments.

Do the same thing here, and those two went away. So now we've got this payload that has an implicit any type. We'll do this one in line.
>> Mike North: Type.
>> Mike North: And the type here is gonna just be data. It takes, like the value is this object array is here.

Let's see, why is it complaining?
>> Mike North: I think the C should be above it or something, let's try that. Sorry there we go, param. So now if we hover over this payload you can see, hey it's not just like a random thing. It is an object that has a property on it called data and the value can be pretty much anything.

And as we iterate over this, you can see there are my listeners. That's an any array. I think it can infer enough there. It's not using any implicit anys. Let's see what happens if we do something like this.
>> Mike North: Type,
>> Mike North: Something like that and we go down here.

>> Mike North: There we go. So now, this is not just an array of anys, it's an array of functions that take an object as an argument and return nothing. And so even when we're in here, like this thing here, we know what it is, right?
>> Mike North: So x, it's telling us basically it takes an object in there and returns a void.

>> Mike North: All right, so here, why are we complaining about this? Object implicitly has an any type. Fine, we'll say it's an array.
>> Mike North: We'll say it's an array of anys.
>> Mike North: Let's see, items, we'll give it a name, something like that, yes?
>> Speaker 2: I had another question in chat.

>> Mike North: So if you're in my libraries,
>> Mike North: If my libraries.d.ts is not published but you do have it, do you just place it at the root of your project? So if you have in the root of a project for your type definitions an index.d.ts, that will get picked up automatically.

So if you have that and it's part of your mpm module, consumers of your mpm module will pick up on those type definitions. If the file has a different name, you may need to finesse the compiler configuration a little bit and you'll see I've got this paths file down here.

So let me get rid of this, it's paths within compiler options and that's where we would say, okay, I'm gonna ask for this muicss which is this little mini material design library. But here's where you can find the modules of interest, and that sort of, this mapping is used whenever you import and something is present here.

That will be used instead of the normal conventions.
>> Mike North: All right, so let's keep plugging away here. We've got now three files, we'll focus on those. Let's start with the grocery item store. So here,
>> Mike North: Data item has implicitly has an any type. So you've got update items and wherever this is used like given an array of grocery items, add new ones.

So this given an array of grocery items, like that sounds like an array of something called like that. So we need to define this up top. And we will augment it as necessary. So here we've got update categories, we've got some JSON data coming back, and in this case, like item.

This is a good example for me to show a case where there's something sort of deep in our code here. I happen to know that this here is an object that just has a category property on it, that's it.
>> Mike North: Something like that.
>> Mike North: We need one more set of braces so the first set of braces says, I will define my type here and the second one says, I am an object.

And still has the implicit any type.
>> Mike North: You know what we could do, there's a different way to do this, arguably a better way than what I just did. So we'll say categories. We're gonna cast that,
>> Mike North: Or define that as an array of those things.
>> Mike North: Something like that.

So now we've got categories and category names. And we've sort of said, based on this end point, I know my structure's gonna be this. And here's an example where it might be overblown to create a type definition that says please expect an array of objects that have a property on them that's a string, that's under the property key called category.

>> Mike North: And now that's happy. So categories, that was known to be a string array, and now we've got that as a string array, everything's happy. Okay, so here, on items updating, updated, it's passing something into fire. Fire wants an any array. So now we're getting into a situation where really we just need need an array-like thing.

We don't necessarily need a mutable array like capital A array. So if we go in here and we change this a little bit.
>> Mike North: Bring back any is not [SOUND]
>> Mike North: Actually this will work just as well. So this.items is a read only array.
>> Mike North: So read only array and this one wants to receive an any array, you could do it like this.

We're gonna create a union type here, so this is an or operator.
>> Mike North: No, still don't like it? Push is missing from read only array. All right, let's come back to that one.
>> Mike North: Okay, items implicitly has an any type because with an empty array, there's no way to know exactly what we expect to put in here.

But, I happen to know this is a cart store, so we're gonna have an array with something we'll call a cart item.
>> Mike North: We have to go define that up at the top here.
>> Mike North: Wrong.
>> Mike North: Okay, and now it's saying, so this is the same issue as before.

We're gonna leave that in place.
>> Mike North: Actually, that's all we have left here. So argument of type, read only array any is not assignable to parameter of type
>> Mike North: array double bracket.
>> Mike North: Cuz push is missing in the type read only array. Now, I don't really need to push anything in here.

>> Mike North: So I should be able to do this. Now this here,
>> Mike North: Let me make sure that I'm not just lagging behind in terms of
>> Mike North: Type checking here.
>> Mike North: I do need to just change this up here. Array like any and now we're down to no problems.

So you see, this forced me to basically go as soon as I had to deal with an immutable array of any type, and there were certain situations where I was getting a read-only array which would be, let's see. Where is that ultimately coming from? Item object freeze. So this is a case where I basically said, okay give me read only copy of this item like consumers cannot mutate this, you can just read it, that's it.

You cannot add, you cannot push things into this array. So then that forced me to go back and basically relax constraints all the way back to defining what a listener looks like, so that it is ready to receive this. Now it wouldn't have been forced to do that in JavaScript, but his is now, whoever consumes that code, whoever is building listeners and registering them, they know that potentially the array that they get you cannot push things into it, right?

Now my intent is clearer, right? Because when you're adding a listener, it has to look like this. It's just an array-like thing and all you're allowed to do on an array-like thing, it doesn't have a type definition, there it is. It's just got a length and you can grab things off of it.

You're not given license to use the full spectrum of array functionality. All you're guaranteed is you can do that which is great because now, it works for read only arrays as well. Whereas otherwise, you would find that runtime, one array in one scenario, it's gonna end up being read-only.

And now, the function push cannot be found on object, whatever, whatever. And you might have to get into the just perfect situation for user to discover this problem. Whereas now, we have moved that into build time where we said, all right, ArrayLike, that's all we need, everything should work fine.

It's a very low, this is a super simple, super simple shape of an object, just two properties. And in this situation, it is all that we need. And so that's what we're gonna use. There's no need for us to get more specific, to say give me a mutable array.

I don't need it. All I need is this.
>> Mike North: And now we're done at zero problems. So you've added type information and as a result, our auto complete is better. We've clearly defined the constraints that we need in order for our code to work and anyone else that would like, if in a listener, you attempted to like here, where would this work?

It would be in a listener that fires. Where is my register happening? I can use find symbol and file. Actually we'll go back to listener support.
>> Mike North: Find references. Go here.
>> Mike North: Okay, so when we register a listener and we've got this item update listener here
>> Mike North: That's where we've got this thing here.

So if we had a list of things.
>> Mike North: Then we should really, this would have to be ArrayLike or something for us to add this. Cuz now we're fully in Typescript land. But we can mix this in, just the same.
>> Mike North: [SOUND] So this would be, sorry, a function that takes as an argument an array-like thing.

No, not happy?
>> Mike North: All right.
>> Mike North: No, we can do it the same way.
>> Mike North: So this would be the equivalent. And then in here when we have,
>> Mike North: The listener being defined, there it is. Now we've really only got length. That's all that's available here. So if I tried to do list.push, nope, not allowed.

Now without going so far as defining that type information, you would totally be allowed to do this. You would've said, well it's an array. I see it's using the word here a mutable array is being used. But now, to get all of our warnings down, we had to really make all of the static analysis cases that could be uncovered work.

And so, we've tightened it up quite a bit. All right, so hopefully, I've made a pretty compelling case for adding type information to your JavaScript. Let me make a quick commit here. And this is, let's make sure we actually work here. And we still do so these are errors that are left over

>> Mike North: I wanna be in
>> Mike North: Git stash, great.
>> Mike North: Little more advanced than what I'd wanna do in,
>> Mike North: In the UI for git here.
>> Mike North: Did I pop?
>> Mike North: There you go.
>> Mike North: And let's proceed to the next topic. And let's proceed to the next topic.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now