This course has been updated! We now recommend you take the TypeScript Fundamentals, v3 course.

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

Mike live codes the solution to the exercise.

Get Unlimited Access Now

Transcript from the "Dictionary Solution" Lesson

[00:00:00]
>> Mike North: So the first thing I want us to think about is defining a dictionary. So can someone help me flesh this out? I know this is not a dictionary. Help me create a dictionary that uses a type parameter. So I can make a dictionary with numbers, or strings, or string arrays.

[00:00:19] What would I need to change here?
>> Mike North: So we've just been talking about generics and type parameters. I probably need something up here. What makes a dictionary a dictionary? How's it different from an array?
>> Speaker 2: All of the values are the same type.
>> Mike North: All of the values are of the same type.

[00:00:53] So we're going to have something, and then T. And how are the values organized within the dictionary?
>> Speaker 3: Key value pairs.
>> Mike North: Key value pairs, and how do we type an arbitrary key access in TypeScript where I can pass in home or Office or iPhone and get a phone number back?

[00:01:22]
>> Speaker 2: So you have that array where k colon and then the type.
>> Mike North: Perfectly described.
>> Speaker 2: Is the k special in any way, or can that be anything?
>> Mike North: It can be whatever we want.
>> Speaker 2: Is that convention?
>> Mike North: So I call it k, because of key. It's the equivalent of naming a function argument, and this is just the type that goes with it.

[00:01:48] There we go. And I'm gonna follow the convention of acknowledging that if I pass in key I might get nothing back. How would I add that to this type?
>> Speaker 2: Or undefined question mark.
>> Mike North: Good, actually, we got two good answers. So I can do it this way and I'm gonna go out on a limb here, oops.

[00:02:34] Yep, looks like the optional is not gonna work. That's a very good guess though, that we, I would expect that to be something that they'd introduce in the future. There's really no, nothing is stopping them. In fact, I don't wanna get too deep into more advanced things here.

[00:02:54] There is a way that you could specify with the question mark, but you're both right in that either we'll introduce the possibility of the value being undefined. Great, so according to the use of these things, if these are gonna be like free-standing functions. The first thing we are gonna pass in is a dictionary.

[00:03:18]
>> Mike North: So we're gonna make it a DictT. It's saying cannot find name T. Anyone have an idea of what's missing here?
>> Speaker 2: [INAUDIBLE]
>> Mike North: A constraint? I don't think we need a constraint right now.
>> Speaker 2: Function T is T.
>> Mike North: Function should have a generic T, right? We have to state kind of up front that.

[00:03:44] This function, like T is not a reference to an interface called T, there is a type perimeter that this function uses and it is called T, great. And I'm gonna add the mapping function here. So conceptually, when we use array.map, how would you describe the function that we pass in?

[00:04:07] What's its purpose?
>> Speaker 2: To loop through whatever array you have?
>> Mike North: Sure, we iteratively invoke that function. And what does the function do?
>> Speaker 4: Transforming it.
>> Mike North: It transforms it, potentially from one type to another type, right? So, in this case, we should probably take an argument of T, cuz we're iterating over data structure that has values of T.

[00:04:35] And we're spitting out something else. I want to introduce another type parameter because that's what we're transforming to. And I'll fill in the function in a second, but we're gonna return a dictionary of these transformed values. Now all that's left is for us to define the function itself.

[00:04:59]
>> Mike North: Arg is a T and it returns an S.
>> Speaker 2: Can you ignore the index argument?
>> Mike North: Can I ignore the index argument?
>> Speaker 2: The second argument in a map function.
>> Mike North: You could, it wouldn't, like in terms of using array.map, that would sort of defeat the purpose.

[00:05:27] The function is the definition of the work to be done. We could make it optional and then just return the same dictionary again, but to me that would be a sign of misuse, right? All we could do is iterate over the array and do nothing. Right, so without instructions as to how to transform from one type to another, I would say there's no point in this.

[00:05:54] So I would keep it mandatory in this case.
>> Speaker 2: I mean like for the function type Arg is T, but then as the second argument of that function Is an index of type number
>> Mike North: Sorry, thank you, absolutely.
>> Mike North: Yeah we could totally do that and we don't need to make it optional.

[00:06:17] Because the way that the type equivalent works, if a function chooses to not receive that argument, that's fine. If we made it optional, we're indicating that we may be providing it, but it could come through as undefined, which is not what's likely to happen, so let's implement this.

[00:06:39] Conveniently, it's easy to create an empty dictionary, right? We're gonna create an empty dictionary. We're gonna loop over the existing dictionary and populate the thing that we're going to return. And then we'll return it.
>> Mike North: So there you go. That's the easy part, and now how do we iterate over an object's keys?

[00:07:10]
>> Speaker 2: Object.keys
>> Mike North: Good, Object.keys(dict), and I'll just use forEach, and this receives a value and an index. And that'll be useful to pass along. And we'll say we're gonna place in the output dictionary, sorry I'm gonna rename this for clarity, under the same dictionary key what do we do next?

[00:07:51]
>> Mike North: Gotta use that function, right? I'm almost done and I haven't use it yet.
>> Mike North: So this function is made to take in a T in an index and return S.
>> Mike North: dict and, dKey. Great, thank you.
>> Mike North: And this is of type T or undefined, right? Cuz In theory, there could be something missing in this dictionary.

[00:08:28] Could be someone who's deliberately placed an undefined value in there trolling us.
>> Mike North: If,
>> Mike North: This item and will return, sorry, not return, we'll only place the output item in this dictionary if it's defined. I've gotta be careful here. I just realized what about zeroes and empty strings and other palsy things?

[00:09:04]
>> Mike North: There we go, that's more thorough, right? So we're looping over all of the keys in the dictionary. We're grabbing each value if it's defined. Transform it, pass it along that, transform it using this function by passing along the original value and the index, we get the transformed value out.

[00:09:22] And now we return this thing. This is a place where we're using, we can point to the places we're using the type parameters, and it's quite necessary, right? So we take in a dictionary of type T. T helps us type the function we're using to transform. And the function we receive returns something and that how we'll be able to infirm what S should and that determines our output type.

[00:09:50] So check out how I can use this. mapDict, do I have one already created, no. So we'll create a, we'll just strings.
>> Mike North: And I'll have a function here that'll take the string as an argument.
>> Mike North: And if I return an array of strings, mapDict will return a dictionary of string arrays.

[00:10:22] If I where to wrap it in an object like this, it's error functions we've already met as a function body. Now it's a dictionary of sort of wrapped values. Notice I had to use type parameters to define what this thing does, but where I'm calling it, this looks relatively simple.

[00:10:47] The types kind of just work, the blanks are filled in, and they're inferred by the arguments that I'm passing to this function. They don't have to be explicitly specified. So this will be like a well chosen use of generics in that it's a really flexible piece of code.

[00:11:08] The types that it returns. You have as much level of specificity and detail that you need in order to carry them forward. And I don't have to provide anything explicit. We'll make sure that the solution to the reduce exercise here will be in the repo. And it follows a similar pattern.