If you already have a subscription, you can sign in.
Enjoy free content straight from your inbox 💌
00:00
We have a type representing some state object, which contains a name string and an age number. And our objective is to create setters for this particular state. So it would have a name function that takes a value of type string because that is what name is, and an age function that takes a value of type number because that is what age is. Now we can actually derive the type for these setters from our state type. Deriving it from the state means that we don't have to worry about keeping the setters and the state in sync. If any of the state members change, the setters will automatically update
00:33
and no surprise, the way to derive these setter type is by using types. Here we are saying that for each key within the state type, the type of the property needs to be a function where the value is going to be whatever it was within the state for this key. So for name, we get a function that takes a value of string, and for age we get a function that takes a value of type number. Now, right now the property keys in the output are exactly the same as the property keys in the input that is name and age. And what would be great is for setters that we could follow the convention
01:05
of naming the individual keys as set name and set age. And we can generate new string types within TypeScript by using template string literals. As an example, we have a type function that takes a property K of type string and then generates a new string based on that called set followed by the first letter capitalized and the rest as it is using the capitalized utility type function. So if it gets passed name, it'll generate set name, and if it gets passed age, it'll generate set age. So we can actually rename the property K within the map type by using an as clause
01:39
and passing K to any type function that you might have. For example, ha, we are passing it to set capitalized K. So instead of naming age, we get set name and set age, and we can verify that it is indeed correct by hovering over the setter type. And you can see that it contains the member's set name and set age thanks to that as clause. Now let's take this map type that we've created and make it a bit more general by accepting a generic parameter so that we can pass in any state that we want. Right now it is operating off of the state type, so let's delete that
02:12
and replace it with a generic argument called state. And ideally everything should have worked out fine, but you can see that we are now getting a compiled time error on axis 4K. And if you look at the error, you can see that it is complaining that the key for state can be anything that is a valid key within JavaScript, which is string number or symbol. Whereas for the capitalized function, it must be a string. Now here's a neat trick within TypeScript. Instead of iterating over key of state, we can actually iterate over key of state intersectioned with string. This will rule out any of the keys
02:45
that might not be strings, and we only get the keys from state that are of type string and therefore they can be used with a capitalized function. This intersection with string is something that you will often use when you want to Rename keys by using the as clause. Now let's expand our example further to create an even more full featured store by adding getters in addition to these sitters. Now creating a getters map type is going to be very similar to creating the setters map type. We take an generic argument for state and iterate all of the keys in state that also match a string
03:19
and generate them as get capitalized K. And for the types of these members, we are simply looking at a function that returns the same type as state looked up by the key member. Now, how do you create a store that has both getters as well as setters? Well, you use an intersection type between setters and getters, and now this generic function can be used to define the nature of a store for any given state. For example, for a person state with name and age, we can create a person's store by passing the person's state to this generic store function. And as an example, if we have an instance of the person's
03:53
we can use set name, set age, as well as get name and get age, and all of this will be type checked.