Intermediate TypeScript, v2

Mapping Modifiers & Template Literal Types

Intermediate TypeScript, v2

Check out a free preview of the full Intermediate TypeScript, v2 course

The "Mapping Modifiers & Template Literal Types" Lesson is part of the full, Intermediate TypeScript, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Mike introduces mapping modifiers like `Partial`, `Required`, and `Readonly` which can be used to modify the properties of an object type. The use of template literal types to create new types by combining string literals and union types and examples of how to use mapping modifiers are also demonstrated in this segment.


Transcript from the "Mapping Modifiers & Template Literal Types" Lesson

>> All right, one more concept we have to introduce before we talk about a couple more utility types here, and they are mapping modifiers. So here's where I want you to look right before the colon, so here we've got ?: here we've got- question mark colon. Here we've got sorry, this one's not in the same place, read only.

So what this lets us do just if we think about, return, we're going through a for loop, we're defining each key value pair, key type pair. Here we're saying okay, as we're defining those key type pairs, make this read only, make this a reader, sorry, make this optional, make this an optional property.

So this is partial, this is a built-in TypeScript utility type, where all we're doing here is going through every single key in T, or in key of T. And we're saying, all right, now an optional field exists on the resultant type, but it has the same value type, it just could be missing if you want partial.

A lot of you have probably used partial before. Required does the opposite, anything that was optional, the optionality is removed, that's what minus question mark does. And then finally read only adds read only's as it goes through each key type pair. Those are mapping modifiers those are the only ones that exist today.

There's one more type we could create You could technically do this, this does not come with TypeScript. This would take a read only object and make it not read only, this made me think of just for fun. Made me think of this, so around the holidays in the United States, hardware stores have to put a sign up like this that says we don't make mail to mail extension cords.

Because you'll set yourself on fire, they will make your house below circuit, so in the spirit of that, don't make this. Read only this is there to help you and I think There's a good reason this doesn't exist. This would sort of strip away things that are helpfully there and valuable intent that some developers left for you there.

All right, this is a related topic, this is actually much simpler than some of the stuff we've talked about, but it fits really nicely with mapped types. Because using template literal types, which effectively are the type version of string templates where you could say, I have some hard coded thing.

And then I have a string variable that I wanna drop into the middle of the template string, these are types here. So what we can do, and it's like identical syntax for the most part, we've got art features, which is cabin tree and sunset. And then we've got colors, and we can use this syntax here it looks just like a backtick template string.

But remember, this is on the right side of the equal sign when defining a type alias here. Look at what we get. Paint_darkSienna_cabin, paint_darkSienna_tree, paint_darkSienna_sunset. We're kind of taking every combination of these two union types and putting them together, and just as it's the case with some other places where you put a union type in this kind of a type parameter.

You end up sort of one by one, taking all combinations of those things, and then them unioning them all together at the end, and that's the resultant type that you get. There are a couple little modifiers that you can add to this I'm not gonna talk about them exhaustively, but these are utility types like capitalize.

There's also, I think, lowercase or title case, but what this would let you do is, you can see we don't have the underscores anymore, it'll take a lowercase string literal, capitalize the first letter. Some of these are useful if you wanted to make getters and setters for, a particular set of literal types.

Agalas, I'm not sure he said can you also use a regex in type equals? I think I understand what you're getting at here. You cannot use a regular expression here, it's almost like backtick strings where you can drop variables, and it's the same syntax, right? Dollar sign and open brace, and you put something here TypeScript doesn't understand or can't expand regular expressions, that's why we have this extends keyword, right?

There's a lot of dynamic behavior that you can kind of put, or a lot of complicated behavior you can put in regular expressions, which would make the type system super slow. Let's look at a little more, Of an example of using template literal types. So here we have an interface, we're calling it data state just imagine this is some properties that you're holding somewhere.

And you could build a type for an SDK on top of that using a mapped type, an indexed access type, and a template, like a string literal type here. So let's take a look at it, so, first of all, the mapped type is really this, it looks like an index signature to this whole thing, right?

So we have a property name k which that's what's looping over, that's the key that's changing every time we evaluate a new property, what are we iterating over? Key of data state, but what we've done is we're saying key of data state as set, capitalize K. And so it's almost like we're saying, iterate over all the keys.

And transform each key, add the word set at the beginning of it, and then capitalize key k, right? Capitalize k, and then for the arg we're using an indexed access type right, this is the indexed access type right there in the square brackets. And what do we get, they'd SDK set digits, set flags, that's coming from digits and flags, there's also a set names here in all likelihood.

There's copilot knows it's true, set names, so you could take an object make a bunch of getters and setters. Something like that, and it can be done programmatically here, which is pretty nice. Data layers sometimes do this where you'll have property, you'll have setters that are based on a field that already exists.

We can use infer In a conditional type to extract type params from string types. So check this out, I've got course website is Frontend Masters, because it's a const declaration, that is a string literal type, it's not just any string, it's the string Frontend Masters. And we're gonna create a new type here called ExtractMasterName, and we're gonna say, okay, it's got this type parameter S.

If S is a subtype of whatever this is, let's look at what that is, It's a string that has a space in the word masters, and we're using infer here. So we're gonna capture whatever is before the space in a new type perm. We'll evaluate that to t, we'll spit out the t if we're able to match the condition and extract, otherwise will evaluate to never, and look at that we're able to get front end out of front end masters.

We've got little bit of string manipulation happening in the type system here. You could take this one step further and you could say, infer T extends Right? Extends a word beginning with F, so this will continue to work, but as soon as I'm saying, It's gotta start with a B, well now it's a never, didn't begin with an F.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now