Check out a free preview of the full TypeScript Fundamentals course:
The "Challenge 1: Solution" Lesson is part of the full, TypeScript Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Mike walks through the solution to Challenge 1.

Get Unlimited Access Now

Transcript from the "Challenge 1: Solution" Lesson

>> Mike North: So let's look at the solution for this first exercise. We're just gonna be working in color-utils, and I'll bring the tests up here. Actually they're still running. So just complete the story here. Npm test color functions. And when this pops up, if you hit Enter, you'll get rid of that little message, and we can see that we're passing the first two tests, which assert that the correct functions are exported from this module, and basically failing almost everything else.

[00:00:40] So hex to RGB, we want that, just if we look at this situation here, and that these, we can kind of understand what types these functions are designed to receive. So hex to RGB should take in a string called hex, or whatever we want to call it, and there's our type annotation and it's going to return.

[00:01:01] Anyone want to tell me what type this function's gonna return?
>> Speaker 2: An object? An object, yeah. Three numbers.
>> Mike North: Okay, so it's an object with three numbers but I'm still missing some information that I need to-
>> Speaker 2: R number, g number, b number:
>> Mike North: Great. And so now the type script is telling us, you have not returned a value that matches this type.

[00:01:35] So we've stated that this must return this thing. And basically every path through this function. For example if we had a condition that in some situation was not returning this, we would get yelled at. It is ensuring that we've made a guarantee, we've stated our intent, and now we have to follow through on it and make sure that whatever this does, it eventually is going to return that thing.

[00:02:00] Here we are going to take in R, G and B, and those, all three of them, are numbers, and it's gonna return a string. And we're getting yelled at for a similar reason here. So it's saying, a function whose declared type is neither void nor any must return a value.

[00:02:24] Void would indicate this function does not, it basically returns undefined. Right, there's no value to be captured. So let's proceed. So for hexToRgb, we've basically got, if you think about our string, it looks like this. FF0000, something like that, and if we break it up, it's almost like we've got pairs of numbers that correspond to each color channel.

[00:02:53] And we have to prepared for the case where we've got something like this too. So I'm gonna do, I'm just gonna have a hacky type solution to this. And we can say something like this. Let RGB equal string, oops, equal hex, and this is, I guess we can't do that.

[00:03:26] So we'll do it like this. So if hex length is 3, then we're going to hextoRgb.
>> Mike North: Sorry, it's tough to talk and type at the same time, hr, hg, hb. So now effectively we've got those three variables representing those characters.
>> Mike North: And we're just gonna basically double each character and pass that in.

[00:04:19] So now from this point on we can know that,
>> Mike North: Our string is gonna be six characters long. We've taken care of the three character case and sort of merged it with the six character case. If I hover over this hexToRgb, you can see in this lower part.

[00:04:41] There we go, you can see that there is there is awareness in this editor, okay? Visual Studio Code knows that this is the function that takes a string, and it returns an object with r, g and b properties. So if I were to pass in something that's not a string, it would complain.

[00:04:58] This is type safety working for us. So down here, I know hat am gonna have a six character hex string. Or assuming I get reasonable input here, right? I guess we could pass in undefined or something, but we won't worry about that for now. So what we're gonna do then is, we want to basically break this up into color channels, and we could think of that as two character offsets, right?

[00:05:23] Pairs of characters starting at 0, 2 and 4.
>> Mike North: So let's say0, 2, 4, map(offset, and we'll then say hex.substring, starting at the offset. And leave it up to offset plus 2. So this will give us something that looks like this.
>> Mike North: Okay, so that's step one. And of course, we can merge a couple things together here and make this more efficient.

[00:06:00] I like to optimize for readability here. So now we've got individual hex color channels, and basically we want to get to them into integers, so hex channel, we're gonna parse in knowing it's 16, and that should gives us something like that.
>> Mike North: We should be able to return that right away.

[00:06:29] So we've got our hexToRgb working, I think in all cases now. At least a bunch of them. So this is gonna end up with something like.
>> Mike North: And this down here is.
>> Mike North: So those were our stages of transformation there. Sorry I have a typo. Great. Now note that, that was that allowing it to compile.

[00:07:00] Interesting. So down here, and by the way, now this is not complaining anymore, this function's done, the type script compiler's happy. For rgbToHex, ultimately, we wanna look at this as, we've got r, g and b values, we need them to be converted to their hex presentation and then sort of smooshed together in a string.

[00:07:23] So I expect we're gonna start with r, g and b like this, and eventually we'll join them together in a string like that. But obviously we have to do some stuff in the middle. The first thing we wanna do is convert, we'll call this a decimal channel, we'll convert that to hex.

[00:07:44] So we can say,
>> Mike North: Convert it like that, and then we'll hit save. And we're still failing four tests. Let's see up here. So if we look up here, we can see the tests that we're failing. This is an interesting one, and we'll come back to it later, this one's telling us something here.

[00:08:09] Can anyone guess what's going on with this test?
>> Mike North: So what's the hex presentation of 2,5,5?
>> Speaker 3: [INAUDIBLE]
>> Mike North: Right. And what's hex representation of 0?
>> Speaker 3: 00.
>> Mike North: Well, we want it to be 00, but I think it's just 0 in this case, right? We don't have that double-digit value.

[00:08:37] So we can just add another map in here, saying, hexCh.length, if it's 1, then we'll just pad it with a 0. Otherwise leave it alone. That should do it, with one exception. So here we can see we're passing in 299. We're basically over-shooting the value of,
>> Mike North: Well, we've got two failing actually let's see, both failing.

[00:09:13] Okay, so in this case we're overshooting our maximum allowed value for r, and we're got 12b, that's the representation of the red channel, and down here we've got -1e. That is the representation of -30. So basically out of bounds values are not being treated well, when we're taking in r, g and b values.

[00:09:37] So what we can do here is kind of box this value in between 0 and 255, and MathMax and MathMin are great for this. So we're gonna take the maximum of 0, or the color channel, whichever is greater. Now we took care of one case and here's the other one.

>> Mike North: And now we're passing everything. So just to show you how you could use this code runner to test this kind of thing.
>> Mike North: You just do something like this. Hit run.
>> Mike North: And there it is. So code runner is a great tool to have in here, especially if you just wanna experiment, like what would happen if I tried this and does this is work?

[00:10:38] So that's the solution to the first exercise, really just intended as warmup and to get us used to annotations here, and to hopefully to help you understand that it keeps us honest where if we pass something, for example, into this parse int, which takes as an argument a string.

[00:11:00] If we pass something else into it, like this, we would have gotten an error, right. And so even as we map over things, basically the types we define when we take arguments into this function, they trickle through all of these functions that we're using. And the reason is, TypeScript has baked into it typed definitions that all of the JavaScript core functionality for the DOM API for a lot of stuff.

[00:11:29] So it's more than just our code that has types along with it. It is all of the code around ours as well.