Video details

JavaScript Marathon: Upgrade to Typescript with Vue 3

TypeScript
03.24.2021
English

"Upgrade to Typescript with Vue 3" with Lindsay Wardell
With the release of Vue 3, Typescript support is built into the framework. In this session, we go through the upgrade process and integrate Typescript into a Vue 3 application.

Transcript

Hello and welcome to JavaScript Marathon, a full day of free online courses in some of the leading Web development technologies and concepts I'm sharing with the stat labs and I will be your marathon host before we get started. We wanted to send a big shout out to our sponsor today. Sinc Phusion, if you are looking for you, I component suite, you should check out their essential studio platform. It includes over sixteen thousand components that were built from scratch with performance in mind. They're lightweight and modular. The platform is really user friendly and devs find it quick to learn. It offers pixel perfect built-In themes that are available in material, bootstrap and fabric designs and an accessible, high contrast theme which, speaking of accessibility, all think fusion controls are touch friendly and render across desktops, phones and tablets, which makes it a great tool for those using adaptive technology. So if you want to make your lives easier and you're working with JavaScript frameworks, flutter blazer, just to name a few. I definitely recommend checking out Sync Fusion by visiting sinc fusion dot com. Check out our upcoming events next week, State of Angular is live on Thursday, April 1st. We have Grathwohl Contributor Day is coming up on April 13th. Modern Webbs state of application monitoring is live on April 20th and our monthly monitoring returns on April twenty. First for women in Tech. For more information, subscribe to our newsletter, The Low Down for weekly updates or follow us on Twitter at the stock labs. JavaScript Marathon is back in May, we have another round of incredible sessions with experts in the deaf community coming back on May 19th. Stay tuned for updates at JavaScript Marathon dot com. Wrapping up our incredible day is Lindsay Wordle, a software engineer at the State Labs. Welcome, Lindsay. Hi. Thank you for having me here. You can find Lindsay on Twitter at Lindsay Kordell. Lindsay is presenting upgrade to typescript with View three. And with that, I'll let you take it away, Lindsay. Awesome. Thank you. So let's not skip the first one I like Sarah said, my name is Lindsay Wordle today will be working on upgrading an application with you three to TypeScript. And here is our agenda for the day. We're first going to talk about what is typescript, in case you are not aware of what it is and why we want to use it. We'll also be talking about why use TypeScript and then we're actually going to perform the upgrade. We're going to do some live coding. I have a view three application that implements using view, has multiple components and uses the view router. We're going to be upgrading each of these parts of the application so that we have a fully typed, scripted application at the end. And then at the end, we'll also be doing a Q&A for any questions that come up during the presentation. So let's dove in. First off, what is TypeScript, the definition here on the screen comes from the typescript website typescript extends JavaScript by adding types, by understanding JavaScript typescript saves saves you time catching errors and providing fixes before you run your code. So what TypeScript can help you do is tell you this was the intent that this was coded with and ensure that you don't start going in a different direction and get lost along the way. The example they give is that a user has a first name and a last name in this picture, but not a name key. So property name does not exist on this type. This is extremely helpful. Well, programing large scale applications so that you know exactly what kind of data you're working with, what structure it's supposed to have and what really is available to do with that data without having to dig through all of the files. So why do you want to do this, why why would you spend this extra time to use TypeScript? First off, an improved developer experience by utilizing typescript and an application, like I said, you'll have a concept of what each of these data types you're working with should look like, what data should be available. Also, it's a more predictable code base because of that. So as you're working in let's say you're in Phenix, you're in a module, you have particular set of data. The the typescript of benefits are going to be that, you know exactly what type of data you're working with in a given action, you know which mutations are available, you know exactly what your state looks like so that your returning data properly and a GETER and also in your template, you would know which values are available instead of I don't know about you. I've had the experience where I'm changing a key in the template and nothing's appearing on the screen. Nothing's appearing on the screen. Eventually I just need to right adjacent to the screen. So I'm able to predict better what's happening in my application by having typed data, entering into my components, into my template, into View X. Also, this provides a certain level of static testing, I'm a big fan of Kansi Dods testing JavaScript course, and in that he talks about static testing being an essential piece of ensuring that your application is stable and functional when you're ready to deploy. TypeScript provides part of that because you're able to determine at development time whether there is an error in your code. Nobody really wants to have their clients. See, the undefined is not a function or cannot find value foobar of. No, nobody wants that. So by implementing typescript in your application, you can test your application statically as you're developing with minimal work once it's set up and running for you. Also, it's in code documentation if you're working with a particular data type, whether it's coming from an API or it's constructed in your UI itself, you know exactly what it looks like. There is a definition of that data in your code. You are able to then expand that as needed, you can write comments around it, but there is a central location for what your data should look like in your code base itself. And that's a huge benefit as you're trying to either add a new feature or you need to do a major refactor. Also, View now fully supports a built in type view, three was rewritten to use typescript from the beginning. So there's a lot of extra benefits that we get by using typescript with you today. So let's get started. Let's dove into what we're going to be doing today, and I will show you here is a test application and this is just a basic UCLA app. It is a test runner. We have a number of tests here. And when you click start tests, they run. Takes a few seconds and all tests have completed, unfortunately, only angular brackets are not round, everything else failed. We'll have to work on that later. There is also an admin panel so that we can add new tests. And now we have the seventh test in our list here. So that's the app we're using the router, we're using view X, we have a couple of views, we have some components. Let's get to converting this into typescript so in our code base. We have our components. We've got four components here that we'll be working on the virata itself. And a couple of views and a single story file. And here we've got the state, the getas mutations and actions. So it's a typical view, three application, very straightforward. Now, the first step that we need to do in order to upgrade to typescript is actually pretty easy to hide. That is, you add, TypeScript, there is in the view cli if you're using something like next to another tool, you're going to have to to look at that specific documentation. For our intents and purposes, all we need to do is use the Vuclip you add, typescript. And that will start to run that's going to add the Vuclip plug in for typescript. It'll be a quick installation and then it'll walk us through what features we want to use, whether we want to use Vue class components, which we're using you three. So we don't need to do that. But if you're using view two, that might be a preferable option or whether we want to have JavaScript as a compatible option. So we're going to go through this. In this case, we are not going to use class style components, syntax. We're going to stick with the options API and we'll do a little bit of the composition API as well. Excuse me, do we want to use Babille alongside TypeScript? Yes. This is a preference in typescript to use Babille for the actual completion and also provides additional functionality such as like it says here on a detective polyphenols transpiring RSX. We're not using JSW today, but it is an option. Convert all James files to two files. So if you're using typescript, you're going to be using mostly Dotts files instead of files for TypeScript. In this case, we're not going to do that. We're going to convert each file separately as we go through the application. And allow James files to be compiled in this case. Yes, what this does is we can use both JavaScript and typescript files in the same application pretty seamlessly. And skip type checking of all declaration files, yes, as we are, it's recommended fraps we are now. So it will finish installing. And it's going to make some changes to our application here, so the main file is now I mean, that's well, that's the only file that's going to change, though. Excuse me, I'm going to get some water while this installs. Great, we'll come to this area in just one second. So the main difference is that we have a mandate to file instead of mandate. I didn't open the file beforehand, but if you're used to a view three application, this is pretty similar. There's there's really no change here. We've got the create apt method are the create a function call you store use router moutet app. Great. That's normal. One unfortunate side effect of running this is that our home view file got blown up into the default hello world that you will see in a clip. So I'm going to revert that change. That's the only file we didn't really want to have happen, Esslin was updated to include TypeScript and this is what this error is here. Unfortunately, the typescript plug for UCLA adds a second extends blocked. We're just going to take the first one out and leave the second one that has TypeScript back. Jason was updated. We now also have this configuration file. This is the typescript configuration. So in this case, it was generated by the Vuclip plug in. We're not going to touch this today. But some of the things that are here, for example, it changes the target to s next. That's what is being built. What kind of module system specify the module co-generation, whether or not we're using strict mode, things like that. The most important thing here for us as a vehicle application is that there is an additional path added for the at sign in Buchla. You can use the at to specify the route of the source directory and TypeScript needs to be aware of that. Otherwise it will not find any of your files and we'll start to worry that there is no type definition for these files. So it sets this block here, sets the path for source to so we can continue using what Fuseli provides. There is also this Shems view Dotts file that is a type definition file. And in this case, it is auto generated to define what a view file should look like from typescript perspective. So this is just a default file, we don't need to touch this. Just be aware that it's there. What it does is define what a component should look like and exports it. So if there is any in the future, this isn't something we're doing, if you need to change, what if you file a single file component? Looks like from type scripts perspective, this is the place to do it. The other file that we got is this, hello, world, we don't need that, we're going to delete it. Goodbye. Great. So now we have typescript in our application. We're not really using it because nothing's been converted to that. So we're going to start with The View store. And in this store that I have here, we have a basic. State, which just includes the list of tests to perform, so originally there are six test defaults to zero when it loads, there is a getter, gets some tests, get the next test ID for adding a new one and the actual test runner status. Some basic mutation's set the tests at the test, update a test, remove a test and saw the result and some actions. And then we export the default for a great start. Great, we are going to convert this file into typescript. Actually, before we do that, I apologize, there was one more file, this is mocking what an external API would be like. So get initial tests, returns, a list of default tests. So we're going to start with this file, actually. So the first thing we need to do is just rename it from test just to test ideas. And if that's all we did, that would be fine. Honestly, that is returning a promise and it has its type. So this is the typescript definition for this function. It is a function that returns, a promise that includes a list of these objects. Let's actually define this object, because what we have here in the results list, TypeScript, only sees that it's an empty array. It doesn't know that this is actually supposed to include something in the in the store. We can see the result includes a boolean of true or false, whether or not the result passed. So we are going to create this type. And what I like to do since TypeScript provides this nice handy thing here, I'll just copy this and I will explain this test. So with TypeScript like that, with TypeScript, we can either create a type or an interface. I tend to go with interfaces except when types are required. So we're creating an interface of test which has this type definition. And I just copied this straight out of what TypeScript was already assuming was down here. So an ID is a no description is a string, status is a string. Well, yes, but status has a specific limit to what kind of string it can hold. So we're going to change that a second. And results is never because TypeScript never sees anything come in here. So the first thing we'll do is change this never to a boolean. And I am assuming at this point some level of typescript knowledge. Please feel free to ask any questions and we can talk about them at the end or after this presentation. You can also look up anything in the typescript documentation, which is excellent. For the status, there are a certain number of statuses we want will change this year, we're going to say Eitel and running and success and failure. So that way, rather than accepting any status, we have these four specific options. So that's our tests fail now we'll go back to the store. And again, the first thing we're going to do is rename this store index, it's. TypeScript isn't going to like this file now, part of that is because it has no idea what some of these values are, what is what is state? It's implicitly hasn't any type in typescript. Any is basically what JavaScript always is. It could be anything. It could be an object, could be a string. It could be a boolean. It could be undefined. So TypeScript doesn't like that by default. You can allow it. But we really want to get the benefits of typescript here. We want to have that confidence in what kind of data is being used. So we are not going to leave this and we're going to keep going, and the first thing I'm going to do before we keep going is just copy paste some changes to our imports here from a little sidewalk. I have currently we were just using create store. I'm going to bring in some types that we're going to use throughout this refactor. You've got mutation, tree action, context, action tree geter tree store itself, which is a type from view permit options and dispatch options that's going to allow us to type our view store completely so that when we're using either the letters or the actions, what have you, it's all fully typed for us. So the next thing we're going to do is write an interface for state and state has a test, which is a list of tests. And for this, we need to also import tests from, I can tell you, password assets test. So now our interface of state has a test test, which is a list of tests we can now define our state here with. TypeScript, when you want to say that a particular variable has a certain type of use, colon and then that type. So in this case, we're saying that state is of type state. So now whenever we're using the state object, for example, right here, you see DOT and VA code already knows that state has tests and if I do test, it knows that this is an array we'll do for each test. And here test is a test. So I can do test dot and I see all the different options, description, ID status. Like I was saying on the test, field status only has those four options. So when we're using typescript here, it only gives us those four options and if I said test, that status equals, for example, it only says you can only do one of these four options. If I said, for example, Tuesday, I don't know. It will say this condition will always return false, since the types of running success and failure and Tuesday have no overlap, which is exactly what we want, we want to have that assistance, that static analysis of our code base rate. So we're not going to worry about that right now. The next thing we need to do is write the interface for our getters and getters. There are three letters. First, going to get tests, get tests, state of state as its input, its argument, and it returns a list of tests. So this is how we can write a type definition for that's measuring almost everything. Right. Detective Edition for our function. Here we go. So get test is a method that takes us an argument of state and returns a list of tests we have now defined what get tests look like. You will also write for the next next custody also takes place, and that returns a number. And the last one here is test runner status. And returns. Well, it could return three different things, right? It could be idle running or finished, so we're going to do the same thing we did with status on the test or the test interface. And we're going to say we're running or finished. Great. And now on this Gedda's object, rather than just saying Gethers, which we could do, that would work, right? We have we have all of our typing now. So get Getraer's test runner status or haptics in state, and it returns Idol running or finish, we're going to use the Geter tree that we imported above, which takes to other types. This is starting to get into a little more complicated, TypeScript. That's your state and others, so this is doing is combining these two types together, Geter Tree is the default type for what, a GETER or an object of getas should be inside of you. And it takes in two different types. One is the the state for this level. One is the root state. In this case, we're working on a module. So these two are the same. But if we were working on a module, this could be module state, for example, and then this would be state. That's the best way to think of it, but in this case, we only have one level for review. We're not worried about that. So we're only going to do state and state and just repeat ourselves. By doing this, we're creating the correct kind of object for us to understand what's going on. And by using the sign and getters, we're still able to fully type out our methods here. So get test takes in state and returns a list of tests as we expect. Great, so that is the getas next move on to mutation's. Interface communication. And this is some shorthand to say the state is. The main benefit here is that we're writing state a lot, we don't need to do that necessarily, so we're just creating some shorthand. So what we want to do now is write the same thing that we did for the getas we're going to be doing for mutation's. We just need to write a definition for each of these methods. So asset tests and test update desk, remove test and start results. So in this case, I'm going to copy them over and then we can just talk about them real quick. So set tests takes a state of S because we're using the shorthand here. This could just as easily be written into Penn State, just like we were doing for the letters. And then it takes its payload is tests, which is a list of tests. And all mutation's return void in typescript void is when you don't return a value. This is similar to other languages as well, like Java C Sharp. So as we've defined our subtests, it returns nothing. So we're returning void. A test takes in state and a test and returns nothing update test takes in state and returns and updated to alert and an updated test and returns. Nothing removed. Test takes in just a test. And so it's a No. And returns nothing and then store results takes in this very specific payload with the test and the results, which is either boolean, which is a boolean, so either true or false. Did this test pass? Great. We're now going to do the same type of thing we did with the getas, with the mutation's, so we're going to type this as mutation, as being a mutation tree with state. And you take. So that way are set tests, for example, correctly has its typing as state of state and tests as a list of tests, and it returns nothing. That's wonderful. So now our mutations and our getters and our state are fully typed. Now on to actions and unfortunately, actions is a little more complicated, partly because we have these different methods of commit dispatch getters, things like that. So that's going to take a little more work. I am going to. Copy some stuff in here and we will talk about it. So the first thing we're going to do, OK. Do they have tape though? Let's say that's mutation's because it's not just one. There we go. So the first thing we're going to do is create a type of augmented action context. And what we are doing is expanding the default action context that comes from view X, we are importing that up here. In the top. And we are going to extend it a little bit to do what we want it to do instead of being more generic, the action context by default provides you with the method that we use all the time in our actions. But it's not fully tied to our needs. It's more generic so that anyone can use it. We're going to make that as tight as possible. So what we're doing is the augmented action context has a type of her, has a key of commit. Where K extends Kicillof mutation's, we're getting all the keys for the mutation. And that sets the key to Kay and the payload to the parameters for that particular mutation. And return type of that particular mutation. We're then also setting the getas, using the same kind of methodology here in Kiev, getas with a return type of getas. OK, so what this does. Is it creates this augmented action context, which can take any generic. Sorry, it doesn't take any generic. We've removed the generic, so. It what it does is create the typing for us by using just the mutations that we have and just the letters that we have, and then we use this special type of AMMIT, which constructs a type with the properties of T, which in this case is the first value except for those in type K. So we are taking in all of the values, all of the keys, all of the attributes from action context of state state, which I explained above. It's just because we're we only have a single level in view X. Except for Comet and Getas, because we've already defined those ourselves, we don't want to use the action context. And so that's the first step. Second step is we need to define our actions themselves. So we create an interface of actions. And we have three actions for our view store. There's initialize test. The context is always going to be this augmented action context. That way we're using our version of Comet and Getas, and if you need to use dispatch, you could do something very similar to what we did for Comet, can use the same type of code. And then our payload in this case is a list of tests, returns, a promise of void, because this is an asynchronous function. Add test, which takes in that same context and a payload of test and run tests, which just takes in the context and nothing else, because running tests is just a command that we're sending off, it doesn't need to inject anything into the. At that point, we can type our actions here with an action tree, just like everything else we've been doing, state, states and Texas. And why is this not returning properly? So first, before I dig into what's going on there, we can see that this comet has a type of tests and the key is set tests. The payload is a list of tests. Which is great, think what happened here is that we did not specify what was coming back from the initial tests. So this error here, this is the type of thing we were talking about with TypeScript giving you that surety and that static testing of your application. So what's happening is it's an argument of type ID description, status results with never, which is the version we didn't like, is not assignable to parameter of type test. And then it tries to explain some things going on. Type string is not assignable to type with these four values. So what we need to do is explain to TypeScript that this method here in the tests folder get initial tests is returning a promise because it's asynchronous with a list of tests. So by defining what this function returns, we go back to our, if you like, store and everything is fine because we can seek out initial tests, is returning a promise with a list of tests. We're properly awaiting it and then we can set tests. What's really cool about all of these type things that we've done up here is that if I wanted to do a comet right here, for example. I see exactly what mutations they have available at test remove tests that test or test result update test. I don't need to go and figure it out. I don't need to go, for example, into a different file because maybe your view is really large. You have your mutations in your actions in different files. This is a pretty common pattern. I wouldn't need to go anywhere to figure out what mutations I have available. Did I spell it correctly or anything like that? It's all done for me because TypeScript has got my back. Great. So that's all we need to do to type the four different sections and as we look in here at create store, we're passing in those values. Everything is wonderful. One quick thing. I'm using this wait for method as in a weight to to wrap my set time out. We'll type that real quick, just as an example. So time is a no. It takes in a number. And this function returns a promise of void. So now it's not the typescript compiler is not concerned that I'm not returning anything from my resolve method call. So that is all we needed to do to make this file work again in the typescript isn't complaining. But that doesn't give us exactly what we want inside of our view application itself. It's just typed for this file. So what we need to do now is create another type, which is type store, and that one is here. Without typos, so expert type of store, we're using that Ammit again to take out which things we do not want and what we are doing is creating an object that is the same or sorry, we're creating a type, creating a type that is the same as the View store, which is the default type definition that comes from View X. . We're creating a view store of state except for the getters, the commit and the dispatch. And then same as we did above for the actions, we're then defining specifically what the commit the dispatch and the Gedda's should look like. Inside of Tikrit, so it's reading our actual list of mutations for the comets, it's reading our list of actions from the actions we created, and it's reading our letters to create the typing for us. Now that we have that, we're going to change this as well, because store equals create store and then we'll export default store. And here we're going to take it as Stort. St.. I'm comparing my notes on 2nd. Yeah, that should be right. There is an error here. We don't. That was the problem. There we go. So one of the things Vaskov was doing was importing store from view for me, as that's its default name. I didn't want that. I want my own version of store. So come on store, which is the few extra we're creating as our version of the store type, which has our dispatch and getas available. And then we just use the strong method and export default. So now this PVC store is available with all of its types if we want to import it into any of our files. So now we're going to do that. First place we're going to go is Edmondo view, so this is our Admon view, which has its header as the list of tests, as an input for the new test description and a button to add the test. And our script tag, we have data for the description and then we're using map getters and map actions to bring and get tests and add test. We have an add test handler to actually perform the add test method, function call and resetting the description to be an empty string. And that's it, so we're going to convert this file into typescript now and get the benefits of all that work we did on The View Extra. First, we're going to change script blank equals keys that will enable typescript in this file. And the first thing that's going to happen pretty much every time you do this is the code or your editor of choice are probably going to blow up and say, hey, we can't find type definitions for things. What's going on? What are you doing? So the first ones to fix are in these imports. TypeScript doesn't know what to do if you have a view single file component without an extension. It doesn't know that that's a view component. It thinks it's typescript and it should be a file or something like that. And it cannot find a module and or its corresponding typed declarations. So all we need to do to fix this is our view to our imports. That should be all we have to do. Because so we're going to change this. There we go. So if we change to the dot dot syntax and move up instead of using the at typescript figured it out and was happy that if we put this back, still in. So we're just going to go with this. Not a big deal. So to Tesla's, you and those two errors are resolved. The next one is this stock description. Does not exist, and that's because when you're using view without TypeScript, you can just export this default object and everything is fine if you will be able to handle it for you. Everything will be figured out. But when we're using TypeScript, that that will still happen. But we need to have that assurance that everything is as it's supposed to. So the first thing we need to do here is import fine components from view. Defined component is a method that takes this object and. Ads, it's types, it's basically what you does after you export this file or export this object anyway, we're just doing it ahead of time. So we're going to export default to find component and we just inject that same object right in there. Wait for my Ed to catch up this stuff description is now a string, hurray, we're doing it right. However, this stupid test doesn't have any types get test. Which is passed in right here also doesn't have any tapes, so we still need to have some work to do. In addition, we're going to play around a little bit with the composition API on this file just to show what that looks like. So first, we're going to import some additional things here. We're going to bring in computed and we're going to bring in ref. We are also going to import our store. And. It's not like we're going to continue doing that at. So now we've brought in our store, our view store, the computed function that we're going to use to create computer properties in the composition API and the rest function for the same purpose. Now we're going to invoke set up rather than data. And what we're going to do is replace the data, the computed and the methods with just the setup. Life-cycle Huq, so that we can have the composition API used here and the first thing we're going to do is futzed description equals if we're going to pass an empty string into it. Right description is a riff of strength, that is exactly what we wanted. So now we don't need the data. We have a computer where we're getting tests to get tests included, computer takes in a function and returns, whatever you want as far as the computer property, which will be. A computer graph of whatever type you're returning. So in this case, we want to store in here, we're going to start seeing the types of benefits from what we were just doing, store dot getters, DOT, and they're all of our gooders. This case, we want to get tests. So now get tests, has the proper type of computer Draugr test. Excellent. Now, we don't need this computer property. And we have the method and it's going to be a function at. And then we need to invoke and test and test isn't here, we're not using anything like map actions, so we can't just invoke, distort and test. What we can do, though, is store dot dispatch a test which is right there, and then add test takes in an object, which is a pit, which is the payload of type test. So what you need to do is put a description which is description value with a ref. When you're wanting to access its internal value in in your set up function, you need to access value on it. We've got the description, we've got the results, which is an empty array just like below, and we have a status and. We have our four different available statuses because everything is fully typed, TypeScript is helping us so much here and just this one simple area. So we want a status of Eitel rate. We're getting an error, though. Because this type is type test and argument with a description, results and status is not assignable to parameter of type test, which means we're missing the. So, again, TypeScript is helping us just with that simple thing, it's saying you're not giving me a test, you're giving me something that kind of looks like one, but it's not one. So now we are good to go. And then because we are using a set up method, we need to return an object that includes everything that needs to be accessible in our templates. Right now, we're getting all of these errors because nothing is actually present. So we need to return ascription tests at test. And then we can remove our methods block. I can take the Ricky. Great, and we no longer need to import view X here because we're not using Navigator's or my actions. And now up in our attempt to get tests as a proper type of a list of tests, the description is still a string. And there is this method test hand, which still returns nothing, but it's using a fully typed add test dispatch. Excellent. Let's now move on to home, and we're going to do the same thing, I'm just going to move a little faster so we can get to everything. So first thing we're going to do is, is just not going to import these things. And I'm going to replace all those dots because it's happening right now. And then we're going to use the contents of this setup function. So first off, before we do that, let's wrap this in different components, just like we did before. And then we need to get test runner status and status with get tests, which is also a computer store, the candidates tests, and then we need the test function, which is basic function. This time I'm going to take it, as promised, for you just to show that typing would look like if we wanted to do it, we could think we just need to copy paste this in here, but we need to get test runner status value just like we did before, so that we're getting the correct actual thing. We're not checking against a ref. We're getting the actual, in this case, idol running or finished status. And then there is the state run tests, which doesn't work at all. We need to do a store dispatch that, not test. And that is it. Oh, I just need to return to status tests in. And. My name get tests. Because it was a little behind there we go, so Tesla is now properly getting a list of tests, test runner status is either Idol running or finishing. Excellent. So we have converted our two components that are using. Using the vector itself into using the composition API, we have imported the store and we're getting all of the benefits of typing as we're programing our application. Now, let's convert a couple of these components here so that the props that are getting passed into them are also typed properly, so that we're going to go to test list. And as we can see here, because we have and excuse me, because we have enabled TypeScript in our application, it's starting to get confused because tests which we're iterating through before test tests is of type unknown. So TypeScript doesn't know what type this is. It knows it's not any, but it doesn't know what it really is. So we need to fix that. So first thing, same thing we did before. Script equals s. And we're going to encourage the. And this time we're just going to stick with the options API. We're not going to do the full conversion just to show what the difference can be and that you can use them both together in view three at the same time. So great. We now have our props and we have our methods. And we also need to test from assets tests so that we we have our test type that all of our tests are supposed to be. Now, first, we're going to deal with this. Props, props, take is tests with a type of array. And this is using the view default type checking, which is wonderful. And it's got a default of an empty array. However, type is an array, which is an array constructor, so that means it's a function and that means we can have some typescript usefulness be put in here. We're going to say array as a function that returns a list of tests. So this as is the same kind of thing as, for example, if we had this test, if we were doing something like that, as does the same basic thing, it's casting the type to, in this case, a function that returns a list of tests. So now already up here, we can see that TV4 test in test tests is a list of test test ID is valid. Test status is one of those four string's test description is real. The only thing we need to fix now is add the view to our Spiner and this method. So this method is generating some classes. And it takes in test, which currently is we don't want any. So we're going to do Kolan Test to get the proper type definition here. So now it knows the test is a test status is going to be one of those values. And what's really cool in this statement while we're here, the first if statement tests status could be one of those four values running success, failure. We're checking for success or else if test that status equals up on the idol running failure. That's because TypeScript knows that success was already checked. We're not going to find success here. It could only be idle running or failure else if test status equals idle, could be either idle or running and so on. So that's pretty cool. So we have at this point converted pretty much our entire application to typescript and we have at least gone over everything you need so that you can start using type's inside of components, using the defined component method, as well as importing your types and importing your view store. The only thing left and this is just going to be a note because we're close to the end, is you can also type your view router. So if we come in here, let's rename this index Stutts. But. And thankfully, nothing breaks here because the router is very simple, we can see that constructor's of type Rotar because Rouda returned it and that route's is being cast by TypeScript into this record roar. And this is something that's really nice about. TypeScript, in many cases, you don't need to define the type yourself. It will take care of that all for you. So we know that this is this object here, route's is being cast into record roar just by being an input to this function. So what we're going to do is bring in ourself right here. So now we've imported it and we can cast this ourselves or not it. We can type it as a list of record. Great. What does that do? The main thing it does is that we now have assistance if we want to add, for example, before enter, so to run next and we can get some assistance here. Next is a navigation guard. Next parameter from is location normalized to is replication. You can start getting some assistance here from TypeScript, and that's because the router is fully typed. And that's one of the benefits of having a library or an application that is fully typed is you can get that assistance as you're writing your application yourself. So if you want to do next, for example, you can start getting assistance. You want query what path do parameters and the US code can start assisting you with that. We should a parameter look like it should be Param. OK, that's good to know things like that. We're not going to dove too much into that because we are short on time. But I just wanted you to see as well. There is a lot of benefit to typing everything in your view application, not just if you like, stored not just your components, not just here or there, but if you go through and actually type everything. There's a lot of benefit and a lot of assistance that you can get from TypeScript and the libraries that build up for you. So I am very happy about all of this. I'm very happy that it's all built into view rather than having to bring in third party libraries and try and shimmied in there somehow it all just works. And as you're building up your view store, as you're building up your application and need some types, it's easy to bring it in. And why not? It's all there and it helps your application be so much better. So. Here is our application, and unfortunately, we ran out of time to do everything, but it still works and that is what matters at the end. So at this point, we'll move on to any questions. Thank you for. This was a great presentation. Thank you so much for sharing your knowledge with the community. We do have a really good question from Alicia Evans. Alicia says, So why would someone want to use a typescript file and JavaScript file together? The main benefit of using and jazz together is in the migration as you're moving into typescript. So if you have an existing application in this case, I was using something that already exists or not already exists. Sorry, it was brand new. If you're using an existing application that's had years of development potentially and you want to migrate into typescript, that's going to take a lot of work. And I am assuming that you're your project owners near your end, users are going to want to continue to have features and bug fixes as you're doing this migration by integrating type scripting and javascript together and having to and files at the same time, you're able to do that migration in a much more scaled approach where everything can be in parallel rather than having to do the full shift in one movement. Great. That is all the questions we have now, if you have questions on the replay or you have some questions later, feel free to drop them here. Also, you can get a hold of Lindsay on Twitter. Her handle is in the chat. And I did want to highlight the GitHub repo for this is also in the chat here. And then, Dev, to Lindsay, do you want to talk just a little bit about this link, what people can find here? Yeah. So as I was putting together this presentation and doing the research myself on how to type everything, this article was extremely helpful on how to type out the back story. So if you want more information on that and you want some additional guidance, there's a lot of comments and discussion in the comments as well on that page. So I highly recommend checking it out if you're curious about this and want to know more. Very cool. Thank you so much for that. Thank you, Lindsay, for joining us. And your first JavaScript marathon. It's been a really, really, really fun day. It was really fun to end this way again. We're back in May, so check out our sessions as they come about on JavaScript Marathon dot com, where the stat labs on Twitter, the media and Twitter come hang out with us at our next event next Thursday. State of Angular. And we'll see you soon. Bye. Thank you.