Transcription
things Good afternoon, everyone and welcome to this workshop on best practices in advanced typescripts tips for react developers. My name is Maurice de Beyer also known as the problem solve for I do a lot of stuff amongst other things. I'm a Microsoft MVP for the community work. I do so workshops like this. I'm a freelance developer instructor. Currently. I'm working for fintech startup in Amsterdam called someday based in the Netherlands as you might have guessed from working in Amsterdam. Although I you should travel quite a bit not so much things go with anymore, but I still like to travel a bit. My websites here my email websites not all that interesting. My email might be more useful to you and my Twitter handle in case you want to send me messages. Now. What are we going to come from? Oh, I'm gonna cover a lot of typescript and react related things. Some of the things are well with react will be interesting if you use react with JavaScript, but that's really not my focus. My focus is using react with typescript. And quite a few of the tips. I'm going to provide you with typescript are actually not specific to react. I'm using them in the react context. But most of those are equally applicable if you write typescript code in some other way. So if even if you would use angular or view or felt or something like that or maybe some sort of site code using nodejs and most of the things will still applicable. You just kind of have to translate it. So some of the things will be looking at is how to deal with props and react components props and typescripts how to declare them how to make them generic for instance deriving prop types from existing components using typescript inferring for things like that and several tricks like that. Then we're going to take a look and to making typescript strict or even stricter than normally because I'm sure you've all heard of the strict option in the TS config where you can set straight to true and typescript becomes a lot stricter detects a lot more potential errors. Well, it turns out that you can go straighter than strict because turning strict on turns on a whole bunch of additional checks, but it doesn't turn the jacket. There are some very interesting ones and specifically one. I always recommend people enable is to know and checked index access which will be taking a look at then. I'm gonna do some validating of data which is strictly speaking not typescript or react specific you could use that with JavaScript on anywhere what you want to in fact, I recommend doing things like that, but there is a nice rich to using it with typescript where you can start inferring again typescript types from Escape masks from the salt schemas and I'm going to do this with sorts, but this is not specific results. I've in the past for instance you up and your pass very similar capabilities. Salt is better in my regards. So that's why I preferred these days, but it's certainly not the only option. We're going to take a look at typescript mappings some of the standard mappings like omit big read-only things like that where you basically can take an existing typescript type and create a new typescript type based on the original one. and what things like commit or pick you can make it create a new type which is smaller or with read only you can create a type which has the same shape, but Typescript won't allow you to make any changes as the name suggests read only says you can read it, but you can't write to it. But we'll also create some custom type mappings where we'll expand on some of these Concepts and for instance. One of the things I'm going to do is I'm going to expand on read only which is not recursive and I'm gonna create that into work workshop read only which is even more useful and relatively easy to make actually they're quite a lot of these type mappings are surprisingly easy to make not all of them a type mapping from a zotsky mat to typescript type is hardly easy, but lots of them are And then in the end, I want to wrap up with looking at how we can Bridge compile time safety where you get fast feedback as a developer with runtime type safety because type predicate and assertion functions and exhaustiveness checking or a mechanism or different mechanisms. You can use which will give you compile time checking which is nice for fast feedback, but it will also give your runtime type checking because in general with typescript you get compile time type checking when you're developing but that runtime, it's just JavaScript. So if one time you're assumptions about your types don't actually work out then well, you might get a random error. You might use undefined somewhere without realizing it. So this is actually a very nice capability. Now you might be thinking that is a lot and we've got four hours and indeed it is a lot because I prepare Workshop like this. I always want to show a lot. I'm think oh I want to show this and I want to show that I want to show Etc. And then I want to talk about all the stuff I want to show And then I end up with way too much material. So what I did is I actually turned this Workshop into a course as well and posted that to udemy earlier this week actually. And I created a free coupon code reacts - Berlin dash 22 as you can see on screen and with that coupon code you can get the course for free. So it's basically all the material we're gonna cover today except I already know in advance. We're not going to be able to cover all of its so I'm just gonna go as far as I can. subscribe to this course free and you can get all the missus man the Man, you don't care far. It's really up to you. Because of the way you do me set up I have to limit the amount of users a bit. They basically allow me to either create a coupon code for a hundred. Uses which is valid for month or one for a thousand users, which is valid for only five days. so not going to advance how many people would be here. I created one for a hundred people which is valid for a month, which means with the number of attendees that it's quite possible that they will run out if that happens. Just send me an email or ping me on Twitter and I'll create a new coupon codes for the next group of people. So you'll still be able to get it. Another thing about this Workshop is we're going to do lots of exercises. Basically, I've got lots of subjects as you saw and each of them is I'm gonna tell you about it. I'm gonna demo it and then you're going to try it. I'm going to provide you with all the code you need. If you want, you can copy him paste it. but if you copy and paste You're not going to remember quite as much about it then if you actually try it, so. Well, if you need to copy and paste just to get things done feel free to do it. But I recommend you type in the code see errors that occur if you make a typo and do it that way because you will remember far more than just by copy and pasting. You don't need to worry about not being able to complete trust. The course each module is basically set up separately. So it's not like, oh I didn't put exercise two now. I can't do exercise three because it builds on top of it. They're all separate. So if you didn't complete to you can just start with three in with the clean slate. No problems there. Now we all need. Some prerequisites we're working machine. I'm kind of assuming that that's okay for everyone because this is kind of targeted not a newbie developers, but it people who are already using reacts and maybe typescript to some degree. I'm not going to cover the basics there. It's kind of assumed. You know that which kind of means you probably are covered here, but you need to have a relatively reasoned version of note installed. Um not sure of 16.17.1 is still current version probably not but doesn't need to be quite as new but at least relatively you I think 14 point something or later is fine. um you need npm. Version 7 or later is going to be fine and having get installed is beneficial not strictly speaking required, but it will make life slightly easier if you do, but if you don't have that that's fine. Now if you want to check whether you have those just go to terminal window and do not. - version and that should give you version the same with mpm - version. And that tells me up on 18.19.2 and I can do the same with gits. And that tells me I'm get using get 2.38.1 on a Windows machine, which I am. Specially with gear. It's just like you can do without get but if you have kids any gets version is basically fine in get one doesn't really matter. We're only going to use it to clone repo and switch branches once. The code is on GitHub. So if you don't have get you can download the zip file instead. I'm going to share a link to the slides in the moment. But if you want to use or need to install anything, all of these images are. Who and that doesn't work? that opens up on my other window my other terminal. So if you click on an image like that, you'll end up like here on the Note website where you can download it just in case you wondering which version current is like to bleeding edge with all the latest version LTS stands for long term support. So in general you want to use the long-term support version, which is kind of the recommended for most people as it says right here. There are the slides again put them kind of assuming that. This is going to be fine. Also, if you want to follow along this link, that's the important one bit totally slash react-t-2022. If you click on that, it will open a copy of the slides and you can see here exactly the same slides with that link. To the udemy course and here the links to all the other stuff. It's also a link to the get a proposed screen here that takes us to the getter repository which contains all the code. We're gonna use. This is basically a next GS application and if we look in the pages folder you can see there are a whole bunch of different pages with all the different steps. We're gonna do in the exercises. I'll come back to this in a moment. Basically each step is a different commits. So you can see the different commits down here show up. There's gonna be lots of slides with codes throughout the slide deck all of those. Are links as well. So I think I've got one on the next page, you know. Where was was on the print? Yeah, like here so. Page like this is a link as you can see if you click on that. It opens the exact commits where that change was done so you can see well. This definition was changed into this part Etc so you can see exactly. What went on? Those were the changes you also see this gentleman John Luke card from the Enterprise combine with his famous make it so. sign you'll see that every time I've basically gone through some acts explanation and it's your turn to do it. I'll open up the breakout rooms in Zoom. So you'll be with well, probably three or four other people in the breakout room. And I can't guarantee you're in the same breakout room every time. in in principle, I'm gonna leave everyone in the same breakout room, but with zoom if your connection drops for a bit Zoom, actually Checks you out of the existing breakout room. And as I don't know exactly who's in which breakout rooms are automatically assigned you're basically going to be added to another one. That could be the same. It could be different one. Not very important, but just so you know. So the first thing we need to do is actually clone the repository. So if I go back to get up here and go to the root. If you click on this screen button, you'll see different ways of getting the codes and if you don't have get installed you can actually download zip file. But I'm just gonna copy URL. I've got that get URL for SSH, but if you use hgps, that's perfectly fine. there go to terminal window and do get blown and pasting that you will like that and it's gonna clone the repository and wrap everything that's there. Not a lot of stuff so shouldn't take very long and butter sites there. With that done. We need to install all the dependent npm packages. So first we're going to do CD into that folder Advanced react typescript 2022 and once in there we'll do an mpm install and as you can see that at least on this slide that didn't take very long. It just took five seconds. So, let's see how long it takes now. npm install Of course, it's going to be slightly faster for me because I've done this before and everything comes from cash or should mostly come from cash. So it took eight seconds. It's probably going to take a bit longer on your machine, but not a lot longer. Once that's done. Basically, we've got the application up and running. Now you'll be on the main branch and the main branch is basically the branch which is all the completed code. So everything should work perfectly fine there, but when we actually want to get started we want to be in a slightly different branch, which is the zero zero Dash start branch. So you need to do it with this command? Or what I typically do is I just start Visual Studio code, which is my preferred editor. and then down here on the left bottom towards the selection for branches and I'll go towards translator starts and that will switch to that Branch for me locally. Then we want to start the application running and in here you can see the npm scripts. There is a Dev script there. So that's the one you want to run either from here or from a console window. Doesn't really matter. so that's running and now that shoots open up in the browser there. And you should see. This list of tasks. So basically a little leather and then different tasks were gonna do you can click on the header to get back to the root? Now because I've switched to zero zero start branched or will be some errors near actually. There are quite a few errors, but some are pretty subtle. You won't see but there are some others like if I go to different typescript the types then you see an immediate error if you're on this branch. We're gonna fix all of those some of them are more subtle. Let's show you one. Let's see. Like here, for instance if I order pizza with mushrooms, then we also get an error, but I have to select exactly. The pizza which has mushrooms if I select anything else like I want this pizza with some olives then everything works fine. So personally error there but it's a little harder to find. There are a whole bunch like that and we're gonna help that typescript help us find those errors and fix them because typescript can do a pretty amazing job if we help it a bit. So here's to start command if used command line npm rundef or if you want to use yarn you can do yarn def. They're resulting application which brings us to John Luke Picard's so to make it. So the first thing I want to look at is how we can compile or more accurately type check the code because we're actually compiling typescripts to JavaScript already when we run it and think show up in the browser because the browser doesn't understand typescript itself the additional type annotation Etc. So in that respect, we're already compiling it, but we're not really properly checking it. And you want to do that because it turns out there is already a compiled error in the code right now. And even though we're running it. We're not seeing that compile error. And in this case, it's actually relatively harmless, but it could be something much more serious and we can't really tell nothing to show us that are things wrong. Now, why is that the case in this case? We're using next. Yes. The same could happen with create react app or feeds or something else. Typically those environments don't use typescript compiler the standard typescript compiler to compile the code all the time because it is relatively slow. Typescript itself is written in typescript, which means it's compiles down to JavaScript, which means that when you're running the typescript compiler, you're basically running JavaScript and while javascripts in node.js isn't exactly slow. It's not the fastest either if you go to will lower level boosting language, which is truly compiled then you can get much faster performance. Now traditionally that will be languages like C C++ Etc. But nowadays there's some popular languages like go and specifically rust, which is very popular in doing these kind of things. And it turns out that next year's uses compiler called swc, which takes our typescripts and compiles it into javascripts and I believe swc is written in Rust maybe it's go but I believe it's rust but which of the two isn't actually that important the important thing is that it gains part of its speed by skipping some steps, which it doesn't need to do. And this part which is skipped is actually checking whether the type the code. As is correct, according to all the typescript annotations. Now the typescript compiler can do that but swc doesn't do that create react app, which were not using in this case, but that you just Babble and by default babble. Does something very similar it strips all the typescript annotations treats the resulting typescript code AS modern JavaScript, which it really is. And then it just transpalded transpiles. That's more than JavaScript into whatever JavaScript you want. So it also doesn't actually type check the codes during that phase. Now create react app does impeller parallel do does? Type checking phase or your code, but even there that's hardly perfect because it only checks go which you ship as part of your bundle. If you go unit tests those will not be typed. Next year's we'll type check your code when you do build which is kind of late because she incredible release builds, but they're the same is true. It will compile the code you shape as part of your bundle, but not the code which is actually part of unit test or other axillary code, which you don't ship so not all the coach is tested. And you really want to type check that code? Now, let's see what's actually wrong. Let's actually first go to the browser. On this page service compiled error yet. If I refresh this there is nothing untoward to see if I open up the console window. It actually shows something about error in the promise. Put that's actually unrelated to that error. It prints out the number one here, which is in first thing but also doesn't indicate any error Etc. So, how can we detect what the error is? If I open up that index. page right here And after brief moment, I see a red line appear here. So I'm not sure how visible that is. But down here you can see there is red line and down here on scroll bar. You can see a little red. Block and that's indicating a typescript error, but that's just Visual Studio code showing me that there is an error do the same. It might not I could use any editor I want. It wouldn't show. And if I zoom down I can actually see here. That's a good variable called not a string. I declare it as type string but then I assign the number one to it. And if I hover over this red squiggly and it's actually shows up. It actually says here. There is an error type number from the number one is not assignable to type string from the Declaration of the variable not a string. so Typescript inverse here. Well, this is a string. Obviously. This is declared as Sorry, this is a number of obviously this is declared as a string. And the two don't match but other than opening decent Visual Studio code. I'm not seeing anything here. Well a couple of ways to fix this and the easiest is to go to the package station and add another command in there. So by default, we've got some scripture here, which we can run. And what I typically do is I add another one and I'll call it compile. And by default it comes with the suggestion to do a next build which makes sense because we're in the next year's application. But we don't want to do a next build because as I said, that would not actually check all our code just to go that we ship. So instead we want to call TSC the typescript compiler. So when typescript is installed, we've got local command called TSC and not strictly necessary, but I want to add. Not quote too much and I do want the space there. I want to add dash dash. No emit. Strictly speaking. Not necessary because there is a t is config file here and that already contains that where is it? No emits right here. So that's actually in place by default, but I like to add it here. So if someone looks at the script, it's clear this compiles but doesn't emit any JavaScript. Who that in place? I can actually run it either to the command line or by clicking on the Run command here. It runs that script and that will type check my code and Report any errors. And indeed here it comes up with exactly the same error we saw. In editor from number is not assignable to create click on. I should be able to click on it and go to defending line. So different ways to fix it. I could turn this into a string for instance. So now I'm assigning the string one to know the string or which is of type string which is probably a bit weird. Um, I could remove to annotation let typescript do which works and now it's just not a string is actually a constant of one. Or I could say this is some number. All different ways of fixing it. Basically that will fix it but down here. I'm still seeing that same error. So let me actually undo my fix for a moment. And let me add another command because I typically use two different commands for this beside the normal compile commands. What I typically do is also add a compile code watch commands and that takes an additional option watch. And when I run this one, it will start compiling but the watch option will keep the compiler active and it will start watching the file system for changes. And any time it detects a change it will read I typically use this with project to only caveat here is with larger projects or compiled watch is going to take quite a bit of time. That's the reason why a lot of modern typescript compilers don't actually type check because of the time. So in that case, I will do the compile as a recommit or a pre push hook of get or just do it manually and do it in the CI environment, but for smaller projects like this, I'll typically have a compiled watch command like this and I'll just keep it active during development. So back to the slides. Here are the two commands. I added the compile and the compiled watch. To compile for well doing one of compile using it on continuous integration server something like that and the compile watch for smaller projects when editing. The air we saw before and of course. which we can fix So I'm going to open up to breakout rooms again for the same three minutes. Please add this compile and compile watch scripts or at least two compile watch because we'll keep that active for the rest of the workshop because we're going to see a lot of compiled error show up when we make small changes to either the way typescript works or some of the codes and that's going to help us fix all sorts of bugs in the code. So let's continue with the next step. So next up we're going to do something. Relatively simple, we're gonna take a look at JavaScript two typescript conversions because right now we're actually using some JavaScript and some typescript components mixed together, which is kind of nice that just works. So if you've got existing JavaScript in you don't need to convert everything to typescript before you can use it, but there certainly some benefits and there's some trade-offs there. So we'll look at some of the options. Now recomponents, you can write in different ways. You can use named functions fat Arrow functions. They all have pros and cons you can export and import them in different ways which again have protein cons? I have a way which works well for me you might want to do things slightly different, but I'm just going to show you a couple of ways of doing it. And let's go to the browser first. Let's close the console window. It will go to Step One. react components or converting rear components from JavaScript to typescript and we've got little message component here, which is hello JavaScript. Well as the name suggests this component is actually in JavaScript. Well, the rest of the application is typescript, and as I mentioned that's actually not a problem. So if we look in here, we you can see here from the top. We're in a DOT TSX file. So the typescript file. This has some code in there. It renders an alert components and if I go to that alert component you can if I zoom in. there decrease in other people j s so in JavaScript file Just playing JavaScript here. Nothing typescript Pacific here typescript or type annotations. Like this is the next page things like that, but it kind of works typescript will already start validating something like let's remove that message ID because that's a required prop. And as soon as I remove it I say we can see a compile error pop up and it actually knows about the message ID being missing. It doesn't exactly know what it should be down here. You can see that the message ID is of type any in the very interests of type. Any there is no type information there at the moment. Even with JavaScript you can type information like there is nothing here, but using JS documents you could actually add type information about these props and typescript would pick those up. So that is an option. But for now, I'm assuming we want to convert all our code to typescript and get the full benefit of type safety. So what you'd want to do is you'd want to rename this file. now with JavaScript, you can name files.js or jsx and originally the convention for react was to use the dot jsx extension. But later that X was kind of dropped and everyone is just using Js. Js. Nowadays, at least that I'm aware very few people still use jsx if you want to you can but there is really no. benefits over adding or removing that X So if I change this little to to the TS? It might sound reasonable to do but it's actually wrong if I do this. My components is compelled and I'll get all sorts of Errors like can't find name diff Etc. Where would JavaScript the extension JS or jsx doesn't matter with typescript it does so I really want to name this file dot TSX. And only because of the file name TSX with the X does the typescript compiler know that this is a red components. I still have compile errors, but at least not as many. If I do this, I also want to stop this death task because it's still looking for that alert.js. So I want to stop this and restart this. so my deaf servers running again. hosting everything on Port 3000 and it's now looking for this TSX file. So let's fix this compile errors. Basically, it says here I don't know about message ID, and I don't know about variance. These two props. So we need somehow to tell typescript what these are like not a couple of ways. You can do it. You can define an interface. And you can name it whatever you want. I typically name props and we'll add a message ID here say it's a string and we'll add the variant here saying it's of type string. and then we can declare that's the parameter object is of type props. And now my compile errors go away. And my coach is perfectly happy and if I go back to the browser. And we're browser window here. If our refresh its then everything is fine. It's still renders, except it isn't JavaScript anymore. So I guess we should change this message. Or was it to hello TSX? And that should actually change the message to hello typescript. this works Now you can Define the prop definition slightly different you can use interface like this or you can use a type. Alias like this and that's almost correct. Then it's an assignment like that. Whether you type or interface is really a matter of preference. There's technically very few differences between the two. interface used to be faster than type Alias like this, but that's also well even faster was relatively speaking. It wasn't exactly a huge slowdown. But even that's is pretty much solved. So in almost every case whether you use type Alias like this or an interface doesn't really matter. If you're into oh, oh like you want to create a class that that implements an interface. Well, it can Implement a type like this just as well or extend. from one interface and from another interface or extent from another type that kind of differences one of the few. I know of the top of my head if I have multiple interfaces with the same name, the Declarations will be merged and with type aliases like this. It's all about an assignment. They will not be merged you if I Define another type here prop it will be considered an error because I've got two different definitions. But it's quite rare that you actually need to do that. But we're still a bit of a problem like for instance. If I removed the return statements my component apparently is completely valid. I'm not seeing any compile errors here. Is a compile error showing up but that's not in here. That's actually where I'm using it over here saying well alerts is not a valid jsx components. It returns void and that's doesn't really work. I guess technically speaking we get the compile error we're looking for but I don't really like it because suppose I'm not actually using alert by commanding out like this. I've got a terror in my code, but it doesn't show up because it's only where it's being used that it shows up. So what I'll do is make this a bit more explicit and say well this is a component so it should actually return a react element. And now I get a compile error here. By by the way, if you maybe you didn't know just but it was automatically imported from react, but I get a compile error here saying well the function actually returns void another react elements because of that missing return statement. So add this back in and now it's fine. But now it's to component that is an error actually causes to compile error not if it's being used in the places where it's being used as if I remove this. I get to compile error here note here where it's being used. Even if I comment this out like I still get the same compiler. Let's fix that again. You might also have noticed I'm using a negative export here not export defaults. That's just my personal preference. I prefer using names exports whether you default export names export is really up to you. There's no big benefit you might also know that I'm using a pretty simple name for my probe definition prop not something which is quite common like calling it based on the components. So something like type alert prop and then exporting that as well. The reason is if I need to get reference to this prop depth definition react actually and typescript give me a much easier way that it can get to component I can get to the component props definition. So I never export these although if you want to find you just don't need to but that means I can just use a simple name is prop because it's just local to this module. Quickly, I don't use named functions like this very often. What I typically do is create fat Arrow functions. So calls alert it react elements and reflect their functioning. Which works out to exactly the same behavior? No difference. Except let's do things slightly different so I can remove this and this and declare the property alert or variable alert. I should say as an FC. with a generic type of prop and not like this that should be FC like this and I need to resolve that. and that mixed up a bit so like this. so FC stands for functional components In fact, if I go to the definition, it's just an alias for functional components. these specify the type of props and it will Define the parameters being of type prop and it will also say well the result is react element or null. You know to allowed value. So now if I removed return again, I get a compile error saying well, I'm assigning a function which does not match that FC definition. So the slightly easier way to do it on my in my opinion. You might have heard of FC getting a bad reputation because it's not very flexible. That's true. There are some downsides to do in it. One I'll show you later in another example where we're going to use generic components, which you can't do with react.fc. Another is that the definition of react.fc has changed over the time? Unfortunately, the type information for react is not done by the react team itself, but separately on definitely typed and because they've changed the definition of FC. It's all of a sudden you would get an update and then your code would no longer compile and one big one day recently did was initially FC would always Define children as part of the props and they removed that saying well if you want children, then you define props with children explicitly. Which actually makes a lot of sense technically because a lot of components don't take children and shouldn't take children like this component for instance. But because quite a few do it actually meant that there were quite a few breaking changes and I for one had to change a bunch of components a bunch of prop definitions and explicitly at children. So it does have a bit of bad reputation still I prefer to do it this way because it is kind of clear but use whatever way you prefer because technically it doesn't matter as long as you define this as the react element. or no actually attack technically more things you return but that's typical thing. You should have asked the result of a rare component function. So that's kind of. converting a component Here actually set up the variant in a slightly different way instead of just a string a bunch of specific strings. That's something I'll come back to in another model. But just in case you haven't seen this this basically means it's very important. It can be any of these values in this case. They're four strings are but there could be a number or so in there as well. And it's only those specific values listed are valid which is pretty neat specially in this case because in this case the variant is actually dependent on a bootstrap style bootstrap class. So not any string would work there. So please make it so. I'm gonna open up to breakout rooms for one more minute. So four minutes total converts that alert.js to a TSX component play around with the different ways of defining it having named function there or using and fat Arrow function like this and FC. For functional component to Define it and see which of those you prefer. I could go into the component and see I could check at runtime see what happens. That's actually do that. So we're on usually exclusive props, and then if I open that we can see it's actually renders. Can we do mutually exclusive props question mark So apparently the message of rules the message ID, but what I'm using this like this, I really can't tell I have to go and either check the implementation or render the component and see what actually happens. And the override it well. If I specify an empty message is still going to be overridden or am I gonna see the Hello typescript message now? Actually, it doesn't I'm getting an empty message. So let's put this back in and take a look at the implementation why that's the case. So good, you will alert text message and message ID both are defined as optional strength. So I don't have to specify both of them. I can leave them out and here we can see the actual message to display is the message. And then the Norco lessons operator format message with the message ID. So if a message is specified and that's Not know or undefined that will be used. So an empty string was used, but if it's null or undefined, so not not past in this case because no is not allowed. Which means undefined then we're going to call the format message function. But that means that this use case is actually invalid. and if I copy this a few times like will make some invalid cases like this is invalid with both. If I don't specify either of them, that's invalid. And if I just specify a message that would be valid and if I just specify the message ID that will be valid. so these two are valid And these are invalid. and and there is actually a slightly more complex case where we can say there is also a variant being added which can be will say danger for instance. This is another optional property of type variants, which was defined here and variant is defined as any of these strings which are basically the bootstrap Styles bootreparents known and supported. So these three? These two should not be valid, but I don't really test that at runtime wanna have some predictable. Should be that's these two are not valid. And in fact what I can't even tell from this, but if I go back to the browser, it turns off because the runtime error now because in the last case here where I'm not specifying either message or message ID it actually fix that and it works again, but I don't want to runtime error. I want to compile some error. So, how can we achieve that goal? Well? One thing we could do is say well these prop definitions should be slightly different. We should have Two possible one which as we've got a message and the other says we've got a message ID. Like this, so now I can pass in either a message and a variant or a message ID in the variance. Except here. I don't really get any compile time error. So that doesn't exactly help me but in my components message and message ID are actually invalid because they're not necessarily there. So this doesn't quite work. The other thing is I want to make the message in the message ID required so they're not optional in those cases. They have to be passed in. Doesn't fix my compile time errors here. But now if I go back to the use case at least this is considered invalid right now. so make some progress but not a lot. So how do we fix these errors? Well if I look at Best at there. It says matches does not exist on type props. The same with message ID does not exist on type props. But the variant it's actually quite happy with why is that well because variant is defined in both cases, and in order to solve that problem for message and message ID. We kind of have to. Put these back in on both cases. So now it's happy again. But we don't actually want the user to allow both of these. So we want to say well if you're passing in the message, then the message ID should not be passed in which we can do by specifying a specific type area, which is never and never is a bit of a strange type. It's Woods. It really says well you can't assign anything. to this prop we'll do the same the opposite way here. So now My message is gonna be of type string here. And the message side is going to be of type string but in my types, well, you can never have message and message ID combined because you've either got this combination. or discrimination Now if you go back here all my component use cases are wrong. So not exactly helpful yet. We might need to make one slide change because we have to say well the message ID which is never and the message here. Are actually optional so you don't have to pass them in. and now they stop to three cases are valid because they only have either a message or a message ID and before I made this last change, I would have to pass in both message and message ID but it's like in the first I would have messages a string and then I would have to say well message ID is never but nothing is never so it doesn't really work this works because I can't pass both in now. One would be assigned to never which is not valid. And empty Jeweler doesn't work because there is no value being provided in either message or message ID has to be a string. So if I did something like message is string like that. It's happy but without It's not and now I've got compile time safety. Let me comment these out so. The compile error should be gone. And it works perfectly fine at runtime and let's see to respond question in the comments message ID should not really been any string for formatting to work correctly. Yes. That's true. The message ID should be restricted to valid. React ntl message key in this case. I could do that because they're actually loaded in type and then the suggestion of type of key of type of message would work. But in most of the real applications, I work on those messages are actually loaded from a surface so they can be translated on the Fly and additional translations can be added so you would not know them at compile time. So that suggestion might work or might not work depending on how you're using it. But in this simple application, they would certainly work. In fact, if I look where do these messages come from? They're defined somewhere in here. You can see I've got just these messages so I can get. The type of message and the keys of message and those would give me a Hello JS. Hello. Jsx. Or hello tsxr. I should say. But in this case the thing was about doing that you will alert. Now this pop definition works fine. There's one thing I'm not quite happy with it. Although it's not a big deal right now, but I've got duplication of this variant. So what we could do is we could say well I want to just have that once so I say I want this. and I want to have that variance and don't need this so we can remove that so everything which needs to be there all the time. And I don't think we need that either. What's your wants to put it back in doesn't matter? So now I've just got the stuff that's always the same defined ones that which is only very in this case, and I've got the stuff which changes between different use cases separated out which makes it even better. So back to the slides. Here's an example of that probe definition. I did. Separating out two different combinations with message a message ID and adding the variance to that. And the compiled time error with the original code. And then of course go and fix the original code and check the various different options there if you want to play around with it, so let's go and do the next step. We're going to take a look at more straight features. I mentioned in the beginning that typescript can be run in a straight mode by default typescript is not but if you use next year's or create react app, then typescript will be in straight mode. You can check in a typescript application you typically have until it's config file. So these config to Jason. like this and you'll typically find a number of settings in there. The number can change but quite often you'll find this setting here strict going through. This actually sets a number of settings for typescript to strict. I'm not sure how many like 10 or so which you could if individually set to true you can also set straight to true and then individually disabled some of them. But it's kind of leads you to think that if you shut straight to True typescript is in a straight mode and then you're all good to go. Which is kind of true but not completely because typescript is in a much straighter mode. But it's not like it will always. Do know everything there is and it's not like it can't be stricter. But one thing you could do for instance. Let's disable this for a moment which by the way you can do normally in adjacent file. You can can't make something a comment but in TS config file, you can actually just comment outlines which is convenient and then you can see that I immediately get compile errors because we're actually depending on strict being true which is the case with quite a few libraries these days quite a few typescript libraries and utilities depend on strike being true. In this case as I mentioned I'm using salt for some validation and type inferencing and salt requires will not complete strict through with it requires at least some of the strict features to be set the true. In general I recommend everyone to keep this. Through and only add more strictness to it. Not remove any I would only disable this if I'm doing some prototyping but then that probably wouldn't use typescript. I just use playing JavaScript and the other case where I might disable this if I'm converting an existing JavaScript code-based two typescript and then having straight through will give you lots of compile errors. So start off by disabling it and then slowly enabled feature by feature. But if you start with a new application in typescript to set it to true if it's not automatically done and leave it there and not make it more relaxed. but they still won't catch all the hours like I mentioned so there are some settings which are not covered by strict and I basically listed them at least as far as I know. This is all of them. Maybe they're actually more now because each version of typescript add new feature, so it's quite possible. There is another one being added. And there things like allow unreachable codes, which you is not affected by setting straight to true and you could disable this and not have reachable codes without a compile error. And no fault through cases in switches is another one which is actually quite useful. That's something which leads to quite a few bucks where people forget break statement in the switch and actually one switch falls into the next and accidentally execute more code than they want to well said no fall through cases in switches to true and typescript will compile or give a compile error if that's the case. The one I actually want to look at is this one? The no unchecked index axis. Because it turns out that using a race or things with index accessories, which could also be objects Etc records can lead to some problems. And let me show you one of those problems. Let's just add some dummy code here. Will create a new new variable. Owns data, and I'm going to asserts or create an array there with a couple of values. So three numbers in there and if I look at data then typescript tells me it's an array of numbers. So right here, it says data is inferred as being an array of numbers. I could put it in explicitly. Wouldn't make a difference. And then I could say something like const. 's item one is data. one and typescript would differ and say here constitem 1 is a number which is correct. That's going to be the number two right zero based. So it's going to be two and that's perfectly true. That's a number. But I could also say item 12 for instance. Now if I all typescript what is item 12, it actually says well item 12 is a number. But is it? If I look at this array. Are just three items in there. So index 0 1 and 2. There is no. certain item there with index 12 This is not going to give me a runtime error. But instead item 12 is going to be undefined, which I can double check. If I do a console.log item one item 12 and we go back to the browser. Where is it and we actually have to go to. the right page and if I run this we see two undefined. So typescript thinks my item 12 is a number, but it actually prints out undefined. And if we look at the yeah that's actually makes sense typescripts. Either that I think someone has their mic and mutants. That sounds better. So, how can we? Get some better type checking from this. Well, that's what that no unchecked index accessed us. So if I go back to the TS config, there it is. No unchecked index access which default to false and then gonna turn it to true. And I'm going to save. I'm going to ignore the compile error for now. I'm just going to go back here. So data is still an array of numbers that hasn't changed. But if I look at item one now, it's definition is changed. It's no longer just number. But it's number or undefined. And the same with item 12 the number or undefined? Now I guess typescript could have done a better job in this case because the array is declared up here on the next line. It's never going to have changed. There's no way that could have happened. So I guess in this specific case we could say that item one is a number and item 12 is undefined. But in almost every case, there's going to be more going on and it wouldn't be quite that simple. So typescript basically says well because you didn't check whether something you do referenced from an array is actually a number is still within bounce of that array. It could potentially be undefined as it turned out item 12 really was and it will treat it as such with the reason or with the result of possible compiled errors like we see right here. And if I go to that code we can see there is this function get X-ray ingredients. It takes a name. And it returns an extra ingredient object and let me go back to the TS config for a moments and disabled no and check index access again. So now everything should be fine. There. It is. No more compile errors. if I look at extra ingredients, it's of type extra ingredients, which is to find a pair so you can see the result bunch of Objects there assigned to keys and if we do reference something we get something of type x-ray ingredients and we return that. Now does it actually work at runtime? Let's see. if I Order a pizza margarita with extra olives. That's fine. But if I scroll down a bit and I take the speed style fungi. And I order it. That's fine. But if I add extra mushrooms. Now we actually get a runtime error. Well, that's the kind of error. I want to catch at compile time that this could happen so I can actually guard against it and take whatever is appropriate whatever action. and that's What will be able to do with this? So now the extra ingredients return to compile error and it just takes Visual Studio code the moment to show up. It's now the errors here. So now we could say well we need to deal with this somehow. So we could for instance used to nalco with lessons operator. I say we've got the name and we want to add some price to it. So now if this actually returns undefined, we're gonna default to a new x-ray ingredients objects with the same name in there and an Enterprise so it actually has the shape which is defined up here no more compile error. That's fine. If I shave Michael Ball error down here is gone. And if I go back to my pizza application, I add some more mushrooms now, no error. Their ad that's better free. Keep in mind what you're doing here is you're making a business decision. This is a technical solution for something which really is a business solution. It is always appropriate. No. In this case, it's probably fine. I do I want to stop selling pizzas just because there is something wrong in my data and I can't add an extra ingredient to Pizza. Well, we're probably better off selling the the pizza with three extra ingredients. but suppose your dealing with really expensive items and you've got some additional item which might cost you thousands and thousands of euros. You will really want to just say well, okay, we don't know about it. I'm gonna give it to you for free. Probably not. So you might actually want to do some completely different you might say well in that case. I will put a statement in here as a if we don't have an extra ingredients like this throw. an exception and I was wondering why the air didn't go away but like this so now I'm very explicitly throwing exception which means that if I place this order again, I'll get this exception and presumably I'd have some kind of error logging system this error would be tracked and locked to do something like Century some air collection service like that and I could go in and fix my issue. So how you deal with this really depends on the application, but at least now we're explicitly dealing with it instead of having its. Internally throw some error where it would be referencing a price from something which is undefined which happens in a completely different place than where the air actually was. So let's get back to the slides. So we saw that snow and checked index axis really useful. I really recommend you always add that to your TS config file and start checking for that of all the extra settings. It's in my opinion the most important one and I really don't know why they didn't just add this to strict. I would have just added it to strict and having a strict which enables like 10 options and then doesn't do important ones like this. It's kind of and funny decision. Not sure why it was done that way but enable this one take a look at the other ones. I really recommend using no fall through with switch statements as well. Others like no unreachable codes things like that. No unused variables in functions. I'm a little bit more relaxed with Their useful, they could lead you to potential errors, but these errors are typically less serious. And it's also like linking tools like islints typically find those as well. There's certainly not bad to enable but there's some what this important. So here's a setting no one checked index access, which I added the fix in this case with the null call doing explicits. error there So the next thing we're going to look at is validating data at the boundary of the application because that's also something which often leads to errors. Now strictly speaking. This is not very react or type specific. But will make the bridge to typescript in another module slightly further down the road. Where we're gonna build on top of this. But first, let me actually show you the problem. let's go to another one validating data at the boundary. Okay, again pizza shop just like before we can add items to its I can add picture margarita with olives and that all looks fine and we can go back to that beat cell fungi, and I can add some mushrooms to it. And all of a sudden are pizzas become really really expensive. It's like the voltage actually shifted over. So this is 274,500 euros and sixty cents not sure about you but I'm not gonna pay quite that much for three pizzas. And if I look at the prices here, it actually looks quite reasonable. So something goes wrong in our application, but what is kind of hard? in this case if we just adds Pizza. For me we can see it's 1095 that looks quite reasonable. But if we add one with mushrooms then all of a sudden the price jumps. Very much and if I just add itself only with mushrooms. we already see that and now if I look at the numbers 1095 1095 0 0.60 again here 0.62 is an additional zero here, but kind of looks like there's something going wrong there with not adding things but doing a string concatenation. And this kind of things happen, even though we've got everything in typescript and everything is typed checked. I know in the code. I'm only adding numbers to numbers. When you get data from some external Source be it and user be it backend system. Then you might have type sharing that it's of a specific type, but that might not actually be true. and in fact, if I open up the devtools here for a moments are refreshed the browser and I go to the network tab so we can see what we loaded if I look at the extra ingredients we can see their extra ingredients and let me zoom in a bit we can see cheese has a price of 50 cents Peroni 75 cents, but if I scroll down a bit we can see that the mushrooms. Don't have a number as a price of 0.6. So 60 cents, but it's actually a string. now the price is typed as A number but that's a compile time check and at runtime. It just turns out that reality doesn't really want to conform to our types. and because typescript is purely compile time check it can check this and it doesn't help so we need something else there. So that was more strict validating Ajax data. Here we can see the rest is loader component, which uses react hook use SW air to load the data from the backend and here it's loading pizzas. Still Jason in here. It's loading deck strain ingredients. And all of that is typed there is this extra ingredient type which is defined here in types of this and the extra ingredient here is actually says well price this number. but as we've just seen that Json file being loaded doesn't actually reflect this it actually has It's like three different things. So, how can we make sure that these things actually align? Well, I'm going to use another library for that. But for that we need to create schema.ts file, please we need to put it somewhere and I typically could create a schema.ts because what we're going to do is create a result schema to validate our types at runtime, so I'm going to import salts from Salt ideas, and I want to Define schema which basically looks like this for the extra ingredients. So we'll create consts x-ray ingredients schema like this and actually x-ray will do first x-ray ingredients. Or a single one. So it's settled object. We say we want to describe an object. So this object so we want these two in there. And let's actually get rid of this and we need to export this. But it's not just string that's going to be Z dot string so. the result string type and the same with the number see DOT number and that's a function like this. So that actually defines my x-ray ingredient schema. And if I hover over that you can see that that's a result objects describing this now. I can be much more explicit I could say this has to be is a number which has to be positive for instance negative numbers or not allowed. Like I say the string has to be say like maybe a regular expression or phone number or an email or things like that this case I'm not going to do any of that. I'm gonna do it really simple but salt is really flexible in that regard. Another thing we're loading is not a single extra ingredients, but we're actually loaded. Where's the loader here? We're loading extra ingredients. So that type actually looks like this it's a record of with a string key and an x-ray ingredient as the data. So let's create a schema for that as well. Export costs extra ingredients schema, which is a subtle records taking an x-ray ingredient as the value you can specify the key. But if you don't salt by default takes a string as the key which is exactly what we want. So with this I can actually validate whether the data is correct so I can go back to this loader here say well once we've loaded this I could do chain on another then call. and we've got some day there and I could to explain gradient schema and say well we want to parse that. like this make sure that it's valid. and I yeah. at lotion bracket to many so now we're loading the extra ingredients turning it into Jason objects. And once that's done we're parsing it and only when and result is parsed correctly. Are we gonna sign it to the extra ingredients and do anything with it? And now I go if I go back to the application we get a nice error message here saying something went wrong. So where does this air message come from? Basically if I Don't have x-ray ingredients right here. I'm displaying some kind of error message saying there was an error so display that and in this case, that's what we see here. And the message says well, there was something wrong. I expected a number but receive the string which was the price and how can we find that well, we have to look at the property mushroom and then the property price which was exactly what we saw and then there are message again expected number receive string which is kind of based. here Now this can be much more complex deeply nested structure with a race. But basically the path will point you to whatever was wrong and The error message will tell you what was wrong. So we could basically go back here. And where was the file? this one opened that find that mushroom remove the quote. So it is actually number save this. And now everything loads fine, and if I ordered that same pizza with mushrooms. We get a much more reasonable. Although not quite as nicely formatted typical javascripts floating Point numbers means that we get a slight rounding error here, but at least it is a proper addition and I guess the code would be nicer if we actually formatted the amount properly, but I left that out in this case because then it would actually complain about trying to format a string as a number. so pretty simple to do with the library like salt it kind of bridges to gap between compile time checking at runtime checking. It's not perfect yet because we currently have this type definition saying an extra ingredient Loop should look like this. And I've got ski mask saying an extra ingredients should look like that and they should match up. We don't have to do it this way. I'm going to come back to this in another exercise and we're gonna combine these two definitions into one so you don't have to duplicate it because right now if I would say the number the price is not the number but say a big inference. I would also have to go and change this as a big end and that probably would lead to other compile errors, but Don't want to synchronize those changes. So question in the Jets instead of sort. Can we use? Yup? Yes. Yep supports exactly this same kind of validation and it also supports more using the typescript types from the salt schema from the up schema. And to be honest. I used you up quite a lot before so salt came around I tend to use yup for exactly this but salt is slightly better so actually switched from you up to short but yep is going to be work perfectly fine for this. If you want to say here's the scheme I defined in this case. I've also got the pizza schema and the array of pizzas game us but in this case because I know you the problem was in the extra ingredients. That's the only one I did but then real life application. I would do this for all data from some external source, so that would include And I would also use this for any data the user could enter so in a pizza ordering application. I would get their address and things like that. I would use result schema already up schema. to validate that as well the fix parsing this pizza and the extra ingredients in this case just with slightly shorter syntax, but does exactly the same thing. So please make it so you can skip the pizza definition if you want to just do the extra ingredient because that's the only one which causes an error. Like I said, okay. So the next exercise will start looking at inferring typescript types and we'll actually not in this exercise between one of the others cycle back to inferring the zotsky mat types in front of the typescript types from the zotsky map. But first we're going to do some other inferring just to see the basics. Because typescripts is really powerful at different types. It's like when I created cons data and I signed an array with some numbers typescript in first. That's that day. That was a type of number array. I didn't explicitly have to tell at that. And it's pretty good at that, but we can actually use that in pretty powerful ways. And let me actually show you an example where we currently have a problem in the coach. if I go to step five in front typescript types you see This blows up, but we weren't having any compiled time error show. Apparently the compiler isn't picking this up, but it can so How can we do that? Well? We can get typescript to infertypes and using the extents. We can limit type. So normally extends kind of means I've got say a class that extends another class or something like that but in a case where you start inferring types and using generics you can use to extend to limit something so we might say, well we infer this specific object key, which we're going to do in a second, but that's key you can pass in must be one of known set so we can see say that the value being valid must extend set of known values. Now that might sound pretty fake but let me actually do it. I've got the code for the component you just saw blow up and the component is pretty simple. It renders some inputs and above. It's caused this function get config item for a bunch of things. So I want to get the first name last name birthday from user. I want to get the employer name and I want to get the straight house number in the city from an address and actually uppercasing. That city as well get config other section and it basically reached that from this object. So it was a user there was an address there the properties on there Etc. But if I look at well, what's first name? It's actually being resolved by typescript as any it really doesn't know what this is going to return. If I look at get over guiding it says it takes two parameter section and item and they're just any strings and if I facts it says here I can take ask for an employer's name. But if I look at the config object in here, there is no employer. There's a user there is an adverse but no employer. And in fact, this is the one which was causing the runtime error. So if I comment that out we can see that it actually works and we get first name will last names empty. First birthday and were showing some kind of address. But again, I don't want this runtime. I want this compiled time part of the problem here is that I used any any basically tells typescripts. Just keep checking. It is any JavaScript object and basically just pretend we're doing JavaScript here. No typescript. Which means that pretty much anything goes and anything well could go wrong will go wrong at runtime, but not before. But why did I add that not just for fun? If I remove this config is actually derived as being the type of that object, but down here the compile error saying well, it's called figure out what config section means and if it can't figure out what that is. It doesn't really know what item after that. Is valid what it could be? and the reason is typescript knows that config is an object which has a couple of properties But the section is defined here as a string so it's like yeah. Well, we can't just use any string on there. It has to be one of the valid things which is user and others. So this should have been a compile error. Employer is not valid there. How can we do that? Well, the suggestion was already made previously. We can actually determine that. This isn't any string that it's a key of the type of type of config so I'm saying I've got a variable config that the object. Take the type from that. So that gives me a typed definition of the coffee act and then take the key of that which okay section can only be the first level objects on there. So user or adverse which shows up. and now I get a compiled time error here saying well employer is not valid so that won't work until I actually add an employer there. And give it something like a name. and the teacher coma and now employers valid as well. But I still have a compile error here. So. Maybe you notice it before but initially the red screen went up to here saying well don't know about config section. But now it's all the way it says. I don't know about config section item. So it's slightly expanded and is now complaining about the item part. I could kind of try to do the same here, but I want to put a key of what? It's well the stuff at the second levels of first name birthday name Etc. How can I infer those or? How can I make this string stricter? That is actually correct? And it should be correct in that if the first parameter is user then first name and birth date is valid if the first parameter the config part is employed and only name is valid or in the case of address Street house number City or valid? I can't really do that easily. I could overload this function and write all of those different options out explicitly, but that would be very tedious and by just changing that string. I can't do that. But when I start using generics I can and I can start adding a generic parameter to this function and basically grab all of this. And say this should be a generic parameter. and with generics you quite often see t which is a terrible name, but for now, I'm just gonna do it brief it briefly. So I've basically said I've got a generic parameter of section, which is called T and T could be anything but now I'm back to the compile error about section here. Spoken say here is t t can be anything but it extends. That key of config. So now section knows that it can be your employer or address the first level keys. With that I can actually start expanding on this I can say well then I want a second parameter, but first i'm gonna change that name Christine is kind of original name used for generic types and it's a terrible name. That's like naming all your variables X Y and Z. It really doesn't describe anything. So it's really the type of the config. So I'm going to keep the tea for a generic argument, although arguably that doesn't make a lot of sense, but I'm going to call it the config. with a lowercase o will do the same here. So it makes a bit more sense. Now, we want to do the same with the item. We want to call this the item. So we need a definition of the item as well. Well again, I can do an extent but extending yeah what? Well, it turns out in here I can actually use this part to index into that config object so I can take all of this. It takes sense that but not specific config itself, but the desection sorry not t section T config. So now the config is user employer or address the item actually depends on the value of the config. So now if I go in there I can see we'll user is valid employers valid addresses valid like it was before but last name is actually invalid. because that's user only has the first name birthday and not a last name. But I could add that and it would be happy. So at last name in there, and that's perfectly happy. But I could not say well, let's get the last name from the employer. Because it there is no last name there. It was only a name there. So it's completely type safe. Turn that back into user. Now it's also knows about results. So the first name is a string and the birthday is actually of type date. And I think all of these are strings as well. Oh the house numbers actually number right here. So it actually infers the types, correct? Now interestingly just to another compile error. Down here. So a little further down. It says well we're setting the value. to a birthday here, which is a compile error. If we look at the value that's actually defined here. As the value which we can assign to an HTML input element, which is a string a number a string array this fell fed it or undefined if we don't want to set it. But something else Rachel object isn't valid so that birthday being a date is valid. So now I can turn that into a string if I want to. and because it's fully type-saved I get the complete type checking and intellisons like okay, let's do that into local they Forgot how it was spelled and I'm just typing it and forgot to e for instance which happens to be quite often. Then I get a compile error like just in the test. Dick mean too low color actually. Yes, I did. Thank you very much. And now we actually fixed another error as a result of that as well. So this is really powerful. using generics and type inferencing like this inferring the type of this config object the following the items and the sections based on what's actually near I removed that last name again. I immediately get a compile error here because I'm not using. Or retrieving the last name which doesn't exist. Really nice. And we'll see some more examples of this in action. So question wouldn't be section make more sense for the type of the section argument. Yes. That sounds very true. Didn't I call it these section? No. It's right this. Please write this should be T section because it's the section parameter. And not the config the T config vote for instance be the type of the config object itself. You're completely right there. fixed so the change I made to the actual get Comfort item to get it fully type shape. So, please go and do this. I'm gonna open up the breakout rooms for I mean, it's again. And after that we'll continue building on top of each inferring options. But we'll do that in the next exercise. Oh before I've got I see there is another Good. This also be so Fusion the property path type to be honest. I don't know. I'm not really familiar with how that works. So maybe that would work. Maybe it doesn't need to look interesting. I'm going to you next next exercise. Where we can actually make our prop type for react components and the whole component itself generic. And again, just like in the previous exercise. It will infer type as needed. But in at the even more flexible level in a rear component. And let me first show you where that will be useful. So we'll go to generic prop types. And basically I've got two forms here. Once you respond for the address and these are basically data-driven, so I haven't coded up this complete form basically code it up a generic forum and then passed in the usual object with the first and last name and another instance of that same opponent with an average with properties and if adapts to change it back and safe. But it's very flexible in that regard where they without knowing it's compile time exactly what types they're gonna work against they still give you to guarantee. That's the compound time types are correct very flexible. you don't go and how we can make that better. So that's the driving prop types no generic prop types we've got this example, which we just saw two forms, which takes two instances of generic form one with the user one. Whatever. And this one takes an initial values which has specific shape and then in unsubmit it gets the changed values. But as you can see when I over it, it actually just takes values of any type and I really want this value to reflect this type and the same here with another instance for that for us. Initial values and the dishes and the I want this object. To be the type of the value. And if I look at the actual implementation of generic form, we can see the prop definition and I can see that there are two enes here and I really want to tie these two. Well, I can do that with generics again so I can say thought process engineer could be done. the type of data and the initial values is the type of data and oops copy the bracket too much and the values is also a type of data now kind of tied those together always going to be the same. Now this isn't quite gonna work, but if this would work. Let's go back to four. Would actually right here it would infer the type being passed into initial values determine that t data is this shape and then in submits actually say, okay. Well the values is going to be exactly that shape. But right now that doesn't work yet. It's still complains a bit and part of the region is right here. It needs to know a generic type of to find props with generic type and here I need to add it. I can add a type in here. That's no problem. Like I could say this is some kind of type where I heart coded to some kind of object. But that's not going to be very useful because now it's basically going to say that my values is some object. I really want. This data type to be inferred by how this component it's being used. And that's one of the things FC won't allow me to do. so I'm gonna change this a bit. I'm gonna turn this into function. And then function instead of fat Arrow function. I'm going to say this returns to reacts elements. And the props are of type. props I still need that generic argument. So I'm going to put in. Type and I typically use the same name but just for clarity. I'm going to give it a different name here. I'm gonna call it the type of the form data. but now I can actually put that declaration there as well. So now it's informed invert from the component usage passed on to the props. used in the initial values there and the unsubmit So now if I check initial values, is that shape? The value is the same shape and now actually get a compile time error here saying well, you used last name with the lowercase. And did you actually went away? Did you actually mean last name with the capital N? Yes. I did. Thank you very much fix that error. the same here house number should be house number with the capital n fix those compiled layers. And now it should work. I still have some compile errors. But first let's check whether it actually works if I had submit I see John Doe. If I change these names a bit. Smith As a Mark Smith. Click submit. It actually says marks Mayfair. So all of that works correctly. But we still have some compile errors. So. It's not quite happy here. But at least we've got the part where this initial values and the values Pops to don't submit are combined. It just down here. It's complaining and one of the reasons is opiate dot keys where We're looping over all the keys in the values object. and just like before We didn't put any restriction on the generic type right away, which means anything is valid but object.keys if I go to the definition you can see that the object being passed and has to be of type object not something else. So we kind of have to put in the same restriction. So I could say where is formed data? No, not this one. this one extends an object and now the error here is gone. We still have an error here because we're indexing into that object based on the key and it doesn't like that. So it kind of says well you can't do that on an object, but it actually comes up with a suggestion somewhere in here if I can see it. That's actually, it doesn't should be something in here about using a record, but I'm not seeing it. But the fix is actually to say well we can't just take any object here. We want a record. Which is a specific object. Which takes two arguments the type of key. So that's going to be a string and the type of data which I'm gonna put to any for a moment. and initials bracket save this and my compile errors are gone. Now just like before any tells typescripts don't do any type checking and that leads to potential issues. Because I'm really saying well. This value could be anything. So what I could do for instance here say let's go to that person. Let's give him a birthday. And let's just put a new date in here for instance. born right now Well, this should give us the same problem we had before we're saying over. Putting a date inside of an input component, which is invalid. So we actually want to replace this any by the types which are valid from here. So string number read only string or undefined. Who does in? And this component still happy but that birthday which I added actually at a typo in the names well, but in fact because a new date is no longer valid. but if I turn this into a date string for instance now the type of birthday it is a string and it's perfectly valid and if I go back it actually adds that birthday automatically for me. It just reflects over the data and shows all of them, which is really nice. So there's a comments about we don't need to reflect the arrow function we could write. like that That looks actually good. So that's might actually be a reason why you don't need to go to a complete normal function, but you can still keep it narrow function, but you still can't use the FC the type the reacts FC type to specify the component put your right. I didn't need to go all the way and make it a normal function. I could have left it a fat Arrow function and we're gentext is but only through in this X-Files because let me actually put this on screen so you can see what I selected here the weird syntax where you have to put a coma after it is because typescript gets confused in a tease X-File because the angle brackets it thinks it's jsx and with the call my trailer license, it's not that jsx. So it's gonna use it as a generic type in adult TS file. That wouldn't actually be necessary. Of course, you can't have jsx in there. But thanks useful additions. Because I actually made the change a bit more complex than necessary. This changed the function wasn't quite necessary. So, please go and do this same change. and I'll open up the breakout rooms and then after that we'll actually Start using that's zot schema and inferring that as well. Actually, that's not the next one. There's one before that but we'll get to that soon enough. Like I said, we're not going to do inferring that salt schema type quite yet, but for first gonna differ for component types derive components prop types to be exact from other components, which is a very useful thing. Because like I said in the beginning when I converted that JavaScript component to time. Apps script and prop types because it's not needed. With my own components I can do so if I want to but with many cases when you're using components or other code from that matter from external libraries, you won't always be able to import everything you need because not everything was exported. And by deriving things you need you can still get at I you might want to. Now the example I'm doing is with component props, but there are also standard typescript utilities where you can infer the arguments or the result type of a function. Or the parameters to Constructor parameters to a class. So they're quite a few of these but I'm Gonna Keep It specific to reacts and infer the component props. Many cases that useful. Let me show you one of those. Last boss can go away. Like we've been having some problems with ordering mushrooms. So I might want to say well, I just want to disable mushrooms. I want to make this option for mushrooms here disabled and not order them because it only leads to issues. So I can go into the coach. Well we've got The picture on menu here and let's see here. Are those checkboxes for those extras? So I say well I want to make this disabled. And not actually with that with extra. Is a mushroom mushrooms? But that actually leads to compile error because disabled wasn't exposed. And if I go to the label check box components we can see it just has a few properties on here check children all changed. Well, I could go in here and say well in that case we also want disabled which is an optional Boolean and I'll can add it here. And need a comma there and then we added here. And that would work perfectly fine. Not compile error is gone here. And if I go back to the running application as she my mushrooms are disabled one select those anymore, but I can still select others. But that's kind of. A TD's approach because next someone say well, I want them read only or I want to beside to unchange event. I want on blur events and I want to expose area attributes and all the others. So adding all of those one by one and adding all those types. It's kind of tedious. So I'm not gonna do that. I'm gonna remove this and do it in a more flexible way. Because in reality, what is what I'm saying is Well, I want to enable all the properties I can set on a checkbox there. Not one specific or two specific ones, but basically I want to allow everything or maybe almost everything from a checkbox. So what I could do is say I want the type of that checkbooks props. so type checkbook props And I don't want to start defining those here. I want to infer them and there is a component. Props type and I can specify the type of the component. I want so the type of the component instance and this will give me a list of all the attribute or all the props it accepts so it could basically say well I want to allow some specific props. or all the stuff understand their checkbox So now right here disabled is allowed and I could do read only for said and required all properties show up. But of course they're allowed there, but they don't actually do anything yet. So the simple way is to say well, let's collect all of those props. In Boston whoop. It's not commas dots. And just to render all the additional props here. So now anything goes and mushrooms is disabled and for instance cheese is enabled. But more components actually slightly broken though and let me show you because one of the things I can add is an ID. And if I decide here that I want to be explicit about the IDS. Say I want the ID of the extra name. And I go back here before if I click to cheese it would actually select the item now actually have to click on the little check mark. Why is that? If I inspect we can see where's the input here? It has an ID of cheese. but the label as an html4 attribute of colon RB colon So where does that come from? In the label checkbox, we're actually using an internal ID and not ID. Passed in except that's part of this prop. So this actually overrides the internal used ID. So I want to be a little bit more explicit about the ID being passed in and use that as this. I can't do this say if the ID passing that otherwise used to one from the new idea which gives us the ID. Because that will digitally call This And conditionally calling she's not but we can put where we're using it. So do that in there. in there and now this is fine except for some reason. It's complaining here. Actually that shouldn't be in order. That should be an end. Now it's happy. and now selecting something by the label should work again. And we can see in here. The ID is cheese and the html4 at root is also cheese so that so better everything works now. leave it like this, but if you look Well checked it's just a standard property over here. I'm just passing that on SS on changed the same. So do I really need to special case those? No. They're already part of this type so I can actually get rid of children as well. So it can get rid of dose. Which means I've got an objects. Empty definition which I think where which actually means that I don't. Need anything special there? I can just do this. Oh that's shortens that. Oh anything special with the checked or don't change so I can kind of say well, we'll just collect those in. all the props and pass them on. Do you think I need to space is the ID if I override that I want to use that? And the children because I want to pass the children on to the label and not to the checkbox itself. And now everything still works. Different items mushrooms you still in? If I add something it still added so that checking actually work. and all because of really simple thing component props just Take whatever comment you want whether it's something I defined in my own code base, whether it's from library doesn't matter. It will just work on any components. If you go to function you could kind of do the same as suppose. We've got a function. Demo, which takes an argument say as is a string. and doesn't actually do anything but I could do something like What parameter types although it was parameter types, but now I forget the actual name of the generic where you can. The type of parameters I looked it up in a second and I'll add that just to show you but lots of functions like that which are really useful. So here the updated label checkbox. And much more flexible. They'd be quickly show you what I did wrong. Like there is a parameter type script type which lets you take a type of function and it will tell you which parameter it is you see, I've got a function defined taking a string and a number and it actually returns to string. So it's in first as returning a string and with parameters you can see it's an array s and string number and you can index into them get specific ones like this or get the result from the function which is string or if I change this to return and Then I check results and that's actually number. But the thing I was doing wrong and that happened to me before that's something to be aware. If you start typing parameter, like it doesn't show up in the intelligence list. You really have to make sure for the typescript realizes that you're working on the type definition and then if you do something like that. no parameters shows up or return type things like that But without the type t or type something in front of it, it's doesn't show up in the intelligence list. And that will throw me off because I was just typing parameter Etc. Let's go do the next exercise. We've got like 50 minutes left will the less than 15 minutes for last part. Like I said good everything but we will be able to do a bit more or the freaking coupon code you have for the online course where you can see all of this. Lost we won't get to so I mentioned good that's having results schema and the types type Nations and keeping them in syncase tedious and we actually can differ type quite easily from the salt schema and that's in we're gonna do right now and something which I do quite a lot in real applications. It's not like every type I'll create this old schema for but every time where validation makes sense I create results schema for and then just in for the time. And then firing it is really simple. There's three set dot infer so supposed to improved. You for type of some schema definition and that will give typescript type back. So let's actually do that. Let's close these and go to the next one. Here, we've got the salt ski mask just like we saw before with extra ingredients. The extra ingredients records. The pizza schema pizzas is an array of pizzas all you providing. And we've got the types which are kind of related. Will we kind of wanted to find those separately? so import and then The pizza type we don't want to get this way. We will do that both infer and then I type of just schema if I hope for over Pizza you can see exactly right get rid of this. We do staying for x-ray ingredients ingredients. girl schema for the X-ray ingredients and for the pizza or winter the schema because they're never imported. And see those are imported. Actually that looks like the wrong it works to let me quickly fix that. Instead should be for schemas in the current folder. So now I can see all the types with simple definition. And now if I decide I want to make a change say I want this part not be number but to be a big end. I Define it in schema I go back check the price and now right here you can see the price on the pizza has become a big end. Much easier much more convenient to do. let's turn this back into number because a vacant as you can see from compile errors is actually go through some other errors. Pretty neat pretty convenience again. Another nice case where typescript can infer types based on other things. The implementation of an infer is not super simple here, but still for the powerful still got a bit of duplication that I don't like we've got a picture in order where we've got the pizza name and price which the type happened to match up with pizza because if I change the price to be big into I would also have to change this one. but we're actually gonna look at that in the next module where we're gonna Create types based on type mappings again, but in a slightly different way. And create one type based on the shape of another type but only take part of it. But that's for the next exercise. So let's go back to the slides and we can see the definitions of the pizza and the extra ingredients type just like we did. And there's John Luke Picard, so please go and make this change. to the types and that question was could you explain general rule of proper interface in a way very simple and in a way quite complex. The complex thing is seeing different this between and the type in interface because the simple parts of the answer is well most part. There are no difference you can use them mixed like for instance of golden export type pizza or is this tune is removed his equal sign. And now image instead of a type. No problem. No difference. It will work exactly the same. one thing though I can do now is I could for instance say I want to duplicate. this and now a daily defined my Pitch for two Shepherd blocks I've got can I see the complete result of Pizza on order now somewhere probably, let's see. or pizza Will it show me? Now it's still only shows me the type. But the fact that there are no compile time errors kind of tells you enough because if I would remove this and save I'll get compile errors. And if our remove one of these two, I'll also get compile errors. So what happens is these two interfaces because they're named the same. They will be merged into one. if I turn this back into a type That won't happen. So do the same there? Not corpses basically complaining saying well, I've got a duplicate good identifier Beach out in order. So these two type definitions are not merged. I really have to define it. So that's the difference. Is that important difference? Probably not. Another different here, I'm furring. based on the schema type and that will always create a type Alias for me never and interface so Oh, I get a error compiler thing. Well, I can't do that. If I Define an interface, I have to start with British. I cannot add something to that. Like this. Well I can do is I can say it's some kind of object and then I can add this. Actually, it doesn't like that. I was expecting it. to be valid I guess that isn't even valid. But as soon mapping types inferring types like that, you always end up with the type A Alias. It's always type never extend. So the we have worked here. Let's try again. I guess not actually this has to go after it but it does work. This way does work with extends. So next thing I want to do is again create a new type, but now for the pizza which was ordered which is the name the price which has to map to the actual Pizza type. And then add some more to its the X-ray ingredients, which does actually have a different shape. And they're useful standard features like omitting big where you can take an existing type and say I want parts of that as a new type. So I could say well Pizza on order now consists of name price extra ingredients. I could get rid of these days. Well, it should be. and that exponent But now if I look at the type you see I've got name price which I wanted but I've also got ingredients and extra in there which I didn't. So it for instance with omit? I can say I don't want to specific properties from there so I could say omits the ingredients. Why isn't it? showing up it should be just ingredients. And now the picture on the order is actually simpler. Although it's pretty hard to tell from this because what you see is how the type is defined and not what the actual result is. This isn't going to give a compile error. But say I removed the price is actually needed. Now you can see that we get compile errors. And I can do multiple properties if I want to do so I could do omit price or for instance the name. now both of those are omitted and in the end the extra picture on order will contain extra ingredients gradients and Extras. But in this case, this is actually exactly the properties I want so instead of omits I could use to pick utility and pixels well for pizza take the properties highly less after here. So take the property which is either price or name and use those and now if I compile and is finding again and the pixel order looks exactly like what it should be. So very useful. They're actually a whole bunch more like let me quickly go to the definitions. If I go to the definition, I pressed F12 Phone Windows, you can see the respect. There's a record to create a record type which we already used recent exclude. There's it only which will use in a bit worst things like church partial to grab a type as they will take all the properties but make them optional not required. Or they'll stir make things not knowable. Saw this already parameters. uppercase string which can be usual if you get into string types. So all sorts of interesting maps you can use. Yeah, there's another mention in the chat about an expand for cursive which shows how to do things. So actually I've got some examples on how to do that if we get to it. but first let's go back to the slides and see the change. I just made so we pick from Pizza the name and the price when I have to choose between pick and omit it's I typically go with well, do I want everything from a type except some things and if that type is expanded do I want to automatically also add those new properties? Or is it the other way around if I expand the type a new properties are added do I want to ignore them on this specifically added in this case? I'm specifically interested in only the name and the price and if I add new properties to Pizza, I don't want to add those to the pizza on order by default. So I'll use to pick but if it's like, but I would want to add them by default then. I would use to Omit instead. So please go and Do this. I'm gonna open up the breakout rooms again for three minutes. And after this we'll take a look at some more mappings to read only I just mentioned to see how that will help us find even more errors in our code base. But that's for the next exercise. So next exercise. I want to take a look at another type mapping which I briefly showed in the definition file just now to read only type mapping where you can take a shape of an object, but turn it into read only type. And the reason that's by useful is by default typescript is very much like JavaScript, which makes sense because it's a super set of JavaScript and in JavaScript everything by default is updatable. But if you start using typescript you want to declare what your type shoots and should not do well having all your types just as read write and updateable doesn't always make sense. Like they're cases where that's perfectly valid but also lots of cases where that's not so valid. Sure you one case where that's valid. um using with only step 10 so I've got another instance of the picture shop and I could say well let's order some olives and I've got the picture Margarita 795 if all 8:55 placed your order. You know what I like them. I want to another one. All of a sudden it's become more expensive. That olives which were 60 cents just now are now one euro. turns us to but oats but the compiler could get it doesn't so let's go and help the compile your bits to catch that. And what actually happens is we've got these extra ingredients but the extra ingredients. The price is being updated because of a little hippo in the code. But because it's a root right type typescript things will that's perfectly fine. The runtime of course doesn't care about read only at all. You could use object first to prevent it but either but I could say this is read only. Rep this whole type inside with only mapping. So the result is as you can see here a read-only name and a read-only price. Now if I save this I just hit control s we immediately get a compile error you're saying that the price is being assigned to. And if we go to that code, I've got some stuff here extra for a Euro and I do an order.flatmap and then a DOT filter and then I lock all the extras that cost to euro. So based on that, I'm doing a filter it kind of suggests. Okay. I want to compare the price to one not assign it to one but because the price was updateable. I was actually by accident assigning it instead of a single equals. I wanted to use a double or even better a triple equals there. Make debt change. Compile error is gone. Go back to the browser. Let's refresh so we're going to clean state. Add a pizza with olives 855. Order another one. and it's another buck in here actually So let's actually do it with this one. Because this the price itself is also updated but the price of the olives stays the same. That these 60 cents but there is another book here where the price of the pizza itself actually changes. but we'll do that in the next exercise because the with the only type is really nice, but it's only for a specific object. It's not recursive and it turns out that using. Yeah, but a for map the push itself, they also removed so it's not just for. It's for complex things well, but if you make an array read only then the elements inside of that array are not read only it's one level not recursive read at least produce dimensions. But the best it's how hard will be to create an asset person we can create a deep red only and the example was actually from this link. There's this guy called Butternut he will tweets a lot but also makes pretty useful YouTube videos. So following him in YouTube and on Twitter is highly recommended. And in that it describes recursive nested read only. But I'm actually just gonna code It Up by hand see turns out. It is extremely simple and of cases like that are simple, but first, let me show you why we want to do show Like a previously showed if I add an order would be to agreta and I add another it becomes more expensive and every time it's becoming more expensive like 7,950 Euros for a pizza is kind of steep, but the results are something else going on. Let me refresh the page for a moment and go to the bottom. Let me at a picture of I and notice I can't scroll down scroll bars right at the bottom of the page. Nothing loaded. I add that order and all of a sudden I can scroll down there is a new pizza being added. Yeah metabol at the bottom. And another one has been added. So every time I order something new pizza is being added to the list. That probably shouldn't happen. So both of these cases are things that shouldn't happen. Now we could say well we got the pizzas and we want to make those read only well first let's start with the array of pizzas. So we've got to menu here. So I want to make sure that this is read only. Read only array of pizza. And as soon as I say we get a complete error and if I check we see here that in this space of code where we placed your order, we're pushing a new pizza in that array, so That's one problem solved. Common discount code out and that should take care of adding new pizzas. So if I scroll down to the bottom take the last one place in order no new pizzas appear. But we still have some here with the pizza margarita that keeps on getting more. expensive and there are no more compelled errors. so it's actually go back to the types and take a look at read only. It's really simple. So I'm just going to copy it into our own code. I'm gonna call this deeper it only or deeply nested structure. export this and in the menu, I'm going to turn this into deep read only. So far, I haven't achieved anything. There are no differences because freedom is just a copy of what your original read only was. But what I can do now is I can well. Everything in here nested every property also becomes really which means it will loopho for any object in there. So if there are any nested objects in there, they will again become really and that will go through however Nest many levels you want. So if I save this we immediately get a couple of other errors The second one will fix in the moment, but this one. where it says well We can't change the price and we're actually changing the price on the first beta multiplying it by 10 every time. that's an assignment we don't want so let's actually go there pizza shop. And that's the second thing. the two more errors we have to solve and we can actually solve that relatively simple Right here. We've got the pizza which is a deep root only Beach star and we're adding that to the pizza menu. But if we look at the definition of that that's just regular pizza. Which means we're taking a read-only version of pizza and assigning that to a non-rate-only version. So in this component, we could theoretically start changing that pizza. So by adding the Deep read only here as well. That should be fixed and say for as well. And fix my typo. So now those errors are gone and if I accidentally for some reason I wasn't doing that but if I did some pizza I don't price is one for instance now right here. That's a compiler saying well. It's read only it can't. Be changed and if I undo this change for a moment. Now this would be perfectly legal. You shouldn't do that never in reacts change props being passed in but typescript things this is legal because it isn't aware of that rule and now it won't it will. Stop us. So no more compile errors. the problem with the pizza margarita should be gone 75. It's still 795. so by adding a bit more explicitly what we intend to do with types in typescript. We actually found two more bugs in the code. Which is pretty neat. and now in the interest of time actually going to change this for a moment to what we had before. Because we've just got 10 minutes left so I won't be able to demo this and I think it's kind of nice say here. I had to pick. of the pizza and I wanted that. Price in the name and pick with the key nordenl. and like what I was previously mentioned if you look at this, it's the hard to see some Oh, well Pizza is read only so we'll make this read only if I can type read only that's lowercase. Oh Yeah. so this pizza early because now we can see how it's defined. It's a big read-only of properties with some picked and then some other stuff that but what does that actually results in? Well, I can't really tell without manually or at least in my mind going through all the stuff in there which is kind of hard. Now, let me skip ahead in the slides a bit to the next part. Where I was going to display. the type Customers these other really need utility resolve which is from then from the cam and in his book effective typescript. and if you scroll down a bit towards this resolve type, which basically says, okay, we're solve for type from its definition to what it's actually Defined this so I'll copy that. paste that in here and now I'm basically gonna wrap this whole structure inside of resolve. And if we look at the pizza on order now, I'm don't see read only omits big any of that stuff. I see kind of what it boils down to with name price and next release. I can't see the details on extra ingredients yet because this structure isn't recursive just like with the Deep read only I can say well also go and resolve the nested stuff in there. Now if I look at the picture in order I can see exactly. Well. There was a read-only name price for an extra ingredients but not read only there is an read-only name and price there. So apparently this shoot also be a deep breath only in order to make the extra ingredients read only or I just specified in here like that. Snow I get to see exactly what the result is. now Someone pasted a type definition which I'm not familiar with in it though, but I suspects does exactly the same thing. So, let's see. If I use that, yeah, it does exactly the same. So different way of achieving the same goal. I'm not sure why the one from them from the camera special cases functions. I don't think it actually needs to. I think if I change this back to resolve and I actually say well forget about the function parts that well in this case it certainly going to work because there are no functions in there, but I think in other cases that will work just as well. I've never really investigated that I just used this as is with the nested structure on. There interesting it gives you no runtime overhead because this is purely typescript and it's gone. It's compile time. It does make compilation slightly slower, but I think the fact that you can see what the result is makes it really powerful over having to kind of infer yourself what the result of all that big and read only Etc. So I typically use this quite often on types to see this stuff. So we've got five minutes left. That's the these last two exercises in one go adding the resolve or this expand recursively whatever you prefer that's in the chat window. So useful alternative. I as far as I can tell there was no benefit to one or the other day do the same thing. and at the same time add Deep read only to find the two bugs in the code, which I just fixed and then after that we'll wrap up. The workshop and then I remember we skipped we didn't get to the last part but you all have coupon code for the course and I already know just from my alerts or my phone. That's quite a few people already registered for that. But that's fine. That's what it's for. So I'm gonna skip over the last bits which is interesting. But unfortunately we didn't have time to go for everything which I predicted the front but that's what the course online courses for. You can still see those modules there. There are about the parts down here. Where's my mouse there? The type predicates in assertions, which will give you both compile and runtime safety and exhaust systems checking to make sure where you add something for instance to an enum and you need to cover all the cases with say a switch statements and you've expand the enum that you don't forget to expand related switch statements useful, but no time for that now so we did Cover a lot of other things we covered a lot of cases where there were bugs in code and with some additional settings for typescript either by making things explicitly read only or setting that's no unchecked index access. Setting we can make typescript find a lot of potential bugs and point them out and make us think about better ways to solve them then just letting it happen at runtime. So how we could validate data the boundary not specific to typescript or react for that matter, but still very useful something I do a lot but we also saw how we could actually resolve typescript types based from those salt schemas, which is pretty neat. And as I mentioned that's not specific result. You could do the same with your several other libraries, which can do that as well. But salt is as far as I can see the the best one out there at the moment and if you perspective on that, I'm actually one of the maintainers of the salt. So sorry of the yup type libraries in definitely typed because originally up was written in type in JavaScript not types. It has been Rewritten in typescript, but even though I maintained those I actually switched over from you up to Short. So we see we saw a lot of map types like pick read only. how to create our own with deep red only that resolve things like that The possibilities are infinite like if you want to play around with types, you can do whatever you want. Basically, the type mapping system allows for programmatic Access. You can do conditionals there. You can infer types you can do all sorts of things and do very interesting things. So you can turn typescript type system into a fully functional type or programming language, which is actually completely completely valid touring complete language. So then the possibilities are well, whatever you can imagine. Much much more than we went into or even possibly could cover in a few hours. So with that I'd like to thank you. for attending this Workshop I really enjoyed preparing it. It's looking up all the capabilities and sorting that to present stuff. I will and that you picked up some interesting tips on how you can use typescripts with react or for that matter how you can use typescript without react because very few of these were react specific. It's much more. Generically applicable of course things like a component types is react specific infern component types, but almost everything we covered. Will work outside of a react code base? Which is really nice. Thank you very much for attending. Enjoy typescript. Enjoy react and happy coding. See you all some other time. Bye.