Transcript from the "Template Literal Types & Key Mapping" Lesson
[00:00:00]
>> Template literal types. Not deserving enough of its own section I don't think, but a kind of a cool thing. It's a recent addition to TypeScript. So as of the time of filming this course 4.3 is the most recent TypeScript release. So template literal types have not been around for all that long.
[00:00:26] But I would like to show them to you because especially around data layer stuff they are really, really promising. They look like a great way to make highly reusable things. So we're going to experiment with them here. I have first, a type that I'm calling ArtFeatures, things that could appear in a painting, and then I have colors.
[00:00:56] So using the same syntax that you're used to using for ES template literals, by that I mean the backtick strings where you can interpolate non-string values into a template string. We can create what's called a template literal type. And what we're seeing here, so first, let's look at the syntax.
[00:01:20] We've got the backticks here. We have the dollar sign single brace, we're used to seeing that, right? And what we get, it's sort of every combination of color and paintable art feature. So we've got a darkSienna_cabin, darkSienna_tree, darkSienna_sunset, and now we're going to sapGreen_cabin. And it keeps going and going and going.
[00:01:45] When I showed this to my wife, she said that looks like a factorial. That will tell you how many of these you're going to get, right? It's every possible combination, how many unique combinations you'll get. But these are not good, in terms of, sorry, these are not idiomatic JavaScript method names, right?
[00:02:11] I'm calling this art method names and look at those types, we don't use snake case, right? Not in JavaScript, I mean you totally could. The language supports it, but it's much more conventional to use camelCase. So how would we accomplish this? Well, you have a couple little special things, special transformers of these elements within your template literal type that would let you do something like this.
[00:02:42] Capitalize colors and we've removed the underscore but look at the d in darkSienna. Despite up here it being lowercase, right, the first letter's been capitalized and so we can get some nice method names here. Not a coincidence by the way, the feature set was built such that you could have lowercased property names and then maybe have getters and setters.
[00:03:08] And you want when people are using your code to be able to use these as things that feel like they were painstakingly implemented one at a time when really, it's just sort of an a times b. And here is the format of the string that I want. So why am I talking about this in a chapter of this course called mapped types?
[00:03:33] Well, let's bring it back to mapped types. So what we can do here, some people call this key mapping. And effectively if we go back to our analogy of array.map, when you use array,map, you are converting the values of array A to array B, right? You're just converting the values.
[00:03:56] This lets us manipulate the keys as we're making that transformation. Let's see what happens, right? So here's the mapped type, right? I'm saying I'm iterating over each key and by the way, let me introduce this before [LAUGH] we go too deep in here. Let's say that this is just some piece of data, a record that I persist to an API somewhere.
[00:04:23] I've got an array of numbers, I've got an array of strings, and then this flags thing is a record of Booleans. So I'm gonna pop out into the TypeScript playground, we can play with this. Data state.so we've got digits, which is a number array, here's flags. So I've got dark mode and mobile, those are each a Boolean, maybe little user preferences that someone could turn those on and off, right?
[00:05:01] Here I'm just being yelled at because I'm using this before it's been assigned. But it's equivalent to, Equivalent to something like that. We already talked about record but just bringing us home there. So what this lets us do is we're iterating over all of the keys in this data state interface, right?
[00:05:31] So that's gonna be first digits, then names then flags, and then we're using this as keyword, as is how this remapping can happen. And we're adding the word set in front of it and capitalizing, so we get a little method here that's called setDigits, setFlags and we can pass these things in.
[00:05:52] So if you've written data layer code where you have a bunch of Boolean properties where it's is, is dark mode, is user opt into beta. Well, you could see how you can now in a very generalized way derive some controlled accessors for those kinds of things. Maybe you would use object.defined property to dynamically build something and then be able to represent the types accurately.
[00:06:29] Let me show you a library where I would hope one day they'd use something like this to define types. This is my favorite library for colorizing CLI stuff in JavaScript. And basically, to make this string blue with a red background, you do .blue, and then look at this, bgRed.
[00:06:55] So every colors available as a foreground or background. And now instead of explicitly saying we've got the red and then we've got here's the red and then here's the bgRed. But now you could define this template type that would just add bg capitalized, the R in red boom, and now you can make a really nice API.
[00:07:17] And this library is a pleasure to use, it's very easily proves that you can build beautiful and highly ergonomic APIs. Not rest APIs but functional APIs using this kind of technique. And look, we're now back to catching spelling errors again, we get true type checking here, because I left the E off of mobile and TypeScripts figured that out.