Using Generics with Components 11 exercises
solution

Adding Type Arguments to a Function

Here's the starting point for the useLocalStorage function and how we're currently calling it:


export const useLocalStorage = (prefix: string) => {
return {
get: (key: string) => {
return JSON.parse(window.localStorage.getItem(prefix + key) || "null");
},
set: (k

Loading solution

Transcript

00:00 Let's take a look. UseLocalStorage here. We can see that it accepts one runtime argument here, prefix string, but we're passing it our runtime arguments, but we're also passing it a type argument. This syntax here with these little, what do you call it, angle braces,

00:19 angle brackets, they basically let you parse in a type argument to a function. Here we're parsing in this, but how do we configure UseLocalStorage so that it accepts a type argument? You can see actually if we use const isUseState here from React,

00:37 we can parse in a type argument here if we want to. You can see that if you hover over it, it actually useState undefined, so it's actually being inferred as undefined here. Whereas if we hover over local storage, you can see that it just accepts prefix string, there's none of those angle brackets just here. There are the angle brackets, useState just before the two parentheses,

00:57 and then none here. The way that we do that in TypeScript is we can actually add in a T just here, and this can be anything, so it can be whatever inside here. But T is the convention, so I like to teach and stick with T. Now, UseLocalStorage, it's no longer erroring down here.

01:15 That's great. When we hover over it, we can see that the angle brackets are in place, and they're letting us parse in this type argument. Great stuff. How do we then use that to fix these methods down here? Now, mapUser is still typed as any, and that's because this get function

01:33 really should be typed as this, should be typed as T here. Except not just T, because what we're seeing here is json.parse and then inside here, get the item or return a string with null in it. What this means is if we json.parse null, we'll actually just get null back.

01:52 For this one, this is going to be the T if it succeeds, or we just grab null here. So let's do that. So T or null. Now, this is working. MapUser is now a type of name string or null there. Beautiful. Now, this value here, it shouldn't be typed as any,

02:11 it should in fact be typed as the thing that we get from here. Lovely, lovely stuff. Now, you might be thinking, what happens if the user doesn't parse in this? Because we notice with useState, you don't have to parse it in. Well, what happens is it actually just automatically gets inferred as unknown.

02:28 We're going to see why that is in the next couple of exercises. But this means then that MapUser is of type unknown, and down here, the set function actually receives a value of unknown. So it means that when you have this type of API where you require people to parse the type arguments in, it's good to have it documented and make sure that they do continue to do it.

02:48 So well done, keeping on in our generics journey. Next, we're going to look at inferring these types from the arguments of the functions.