What do you want to learn?
Skip to main content
Play by Play: Angular with Typescript with John Papa and Christopher Martin
by Christopher Martin and John Papa
Learn Angular concepts in Typescript while seeing how experts problem-solve. In this course, developer Chris Martin and John Papa convert an Angular application from ECMAScript 5 to TypeScript, teaching you important concepts and tooling as they go.
Start CourseBookmarkAdd to Channel
Table of contents
Configuring the Environment and Transpiling to TypeScript
Project Overview and Tour
Initial Conversion and Transpiling to TypeScript
Adding Dependencies to Namespace
Completing the Transpiling to TypeScript from IDE
Watcher - Transpiling from Gulp
Watcher - Transpiling from Gulp
Converting ES5 Angular to TypeScript - Model, Config, and Controllers
Angular Configuration Blocks
Let me pull both of these up, too, so we can watch. Okay, can we make this bigger? Yes. So I can see some more stuff? Sweet. There we go. Awesome, so on the left we get the TypeScript, and on the right we've got what it's transpiling to, which are identical right now. Right. So we should start with the namespace thing again. Do that again, namespace app. And go to the bottom, yep. Get rid of this. And now it should generate on the right-hand side. And it did, good. So it's reusing that global variable for us, which is fine, Okay, and now the Angular registration is going to be fine because that's just the name of the module and we're going to call these three functions. The cool thing about TypeScript is, you don't have to use classes everywhere, so TypeScript offers classes, but we can just take advantage of using functions. In some cases, functions are easier. Like the first function its got, is called, init debug. There's really no advantage to turning that into a class. Right. So we're just going to leave that alone, and let it call like it is. The interface for this guy is just a function. Mm-hmm. So, yeah it makes sense just to leave it as such. Now if we wanted to get debugging, we could actually put a type on him, so the compile provider, we could say, dollar sign compile provider is colon of type, it's probably angular dot I something. I compile provider. There you go. I like that tooling. And that whole function, see how it's red at the end of your little, yep, so we do a colon at the end of that, and say this function is a type void, because it's not returning anything. So that would basically, we've TypeScript-I-fied. We've TypeScript-I-fied our code. But notice on the right-hand side, nothing changed. Yeah. Types don't transpile, they just give us type information and tooling in our TypeScript. And again, we have the comments turned on so it's preserving that, it's not mangling that at all. Exactly. Cool, so the next one, we can do the same type of thing. Yep. You're right, so angular, oh this line might get long here. Angular I location provider. Yep. It'd be Enter. Yeah, oh nice, okay. I'll do an angular I router provider. Oh you know what, that's part of the angular UI, so it's probably angular dot UI, yeah! I URL router. Yes. So it'll take some just getting used to where these definitions are located within the Main space. The namespaces of the definition files. I just happen to know that angular UI router has got its own namespace of angular dot UI. Dot, so that's how they separate out they're stuff from angular stuff. Router, URL router provider, that's the one? Yep, then you've got your state provider, which is also part of angular UI. State provider. There we go, so now you've got your parameters have types on them, which means then, if you hover over your URL provider right there, it should give you the type, on the left, yeah. Right there, so if you hover over him, you're assuming your editor will tell you what that is. Not so much? Kind of like in VS, splitter will do that. Right. There's no way. Go to definition review, types. Go to Type declaration? Right, and it's going here, signature there. So it is finding each other right now, cool. All right, now we've got a state provider, and it's telling us it doesn't like what template URL is, and the other stuff there. Unsorted key. Object literal sort key. Oh, tslint, you must have a setting on, where your keys must be sorted. Okay, let's turn that off. Yeah, that's awful. All right, so somewhere in there is going to be there's going to be a sorting or an order. Member ordering. Is it member, or, I already forgot it. Objects literal sort keys. There you go, turn it to false, 'cause we don't want that. We could also have gotten rid of that tslint if we wanted to, so these are options. It's going to help us find some things, like these ones are obviously not very valuable, so we're just going to turn them off. And this one. So you got to go back to app, config. Let's turn this trailing comma off. Okay. Trailing comma. Always on multi-line, we'll just do never. Sweet. Okay. Let's go back to app config ts. Now in our state provider, we've got a state and we're still passing in an object literal to the state, that's perfectly fine, we don't have to use classes there either, so that should be good for it. It's complaining about white space, I believe. Oh, white space, there you go. So all of that looks fine, those are just objects with methods. Now let's go down to init storage. And do the same thing with the local storage provider. Now this was part of our ngStorage definition that we created, and that was ngStorage. Right, we created this one ourselves. Yep, I localStorageProvider. Perfect, I think it will be a void because you're not returning anything. Yep. And set key prefix, fine. Oh, we can use let. We can, so in ES6 or TypeScript, you can use let to say, create a scope inside a function for it. You don't have to, but you could. So we could do let readers, now, is the problem there that readers is a different type? This problem is that our linter is forbidding the var key. Oh really. Altogether, yes. Okay. Which is neat. Sure, we can turn it to let,'cause let's a little more restrictive. And then this error, expected variable declaration. Okay, so it wants us to tell us what this thing is? Right. All right, so readers is going to be, what is that? We could do any right, just do cheat or see, readers. It's getting a list of readers. Is an array. Okay. It's an array of these, these simple objects with IT in them. Okay, so if you wanted to get intellisense in those objects, we could create an interface, or a class of type reader. Okay. Of our own, to do this. Want to do the here for now? Sure, just like we did in the other one, but without the declare? Yeah, yeah, just create a regular old interface, and you can call this thing I reader, sounds good. I reader. Then you got to give it properties like we know it has an ID property, right? ID, and the syntax I'm still getting used to, but I would just do ID String, just like that. Yes, it's an ID of type String, and so that's how that reads, and then you need your little semi-colon. Yep. So that's our interface, and then down below, where it's let readers, the type of that would become array of readers, which is Capital Array. With the generics, right? Yes, using generics. I reader. Exactly, so that does that. Now that works because the property, see down below, inside your if, you've got those ID properties. All those are of type String there. Just for example, change the ID in the interface to number. Now it should tell us down below, that, hey, you know, if this thing wasn't set there, we'd have that problem. Well, the localStorage provider, remember, is taking any. So he's taking any, so he's not being as restrictive. But your readers are actually telling it that. But if, I could do something like this, right? I could cast it to array of type I reader. And will it complain then? Well, see if your editor likes that. So you do that there, and you've got him. It's another type String I reader. Okay, what I would probably do instead, is get rid of the array I reader. And instead, for each of those objects, we can cast each individual one to reader as well. Oh, gotcha. So each one of those would work. We know we're going to be safe, though, so I don't know if I'd worry about it. Gotcha. At this point, we just know that, that guy is going to be an array, and it's going to contain something that matches I reader as an interface. Cool. Now, go ahead. No, I was going to mention that these are used elsewhere in the app. Oh, are they, okay. In our directive, later on. That makes sense. So we could potentially reuse this interface there. We're going to need to take it out of this, well we don't have to take it out of the file. It would be easier. Why don't we make our own file, for reader dot ts and stick that interface in it? Our own file with this in it. Yes. So pull that out. We could stick it right at the same level as app. Like I reader, or? Yeah, just call it reader. Dot ts. You could call it reader interface, reader class, reader model. Right. Generally what I'll have in a project is, I'll have a model folder, and I'll stick all my readers, or maybe it's like customer's orders details. And we'll wrap this in a namespace, too. 'Cause we want it to be in the same namespace. So it'll be namespace app. Good catch. So the advantage of this is, it lets us have all of our models, which in this case is reader, be in once place. Either in one file or some people just create a models file, and they'll put everything in there. And that way, everybody can kind of just, you know, use that for intellisense. U strict, yep. Now that interface is now private to that namespace, we want to use it somewhere else, so we're going to say export the interface. That says, hey, it's not just usable in this, it's usable elsewhere, so it will go back to the other file we were in. I forget which one we were in. App config. Okay. Let's scroll down and take a look at him. The I reader is still being used, it should still know what an I reader is. Yep. Perfect, now we can share it. We don't have to import the file, or anything else because the TypeScript compiler is looking at all those files in that folder. Cool, so another file down. Yeah. All right, we're on a roll. The next one, yeah, one of the controllers. Okay, why don't we hit the easiest one first? That would be home controller. That certainly would be that one, wouldn't it? There's not much in there. All right, so namespace wrap it? Namespace wrap. Now so we're saying that TypeScript has modules, like module orders, like ES6 does. So we could actually define real modules and export them and import them all over the place. That we could do, but this is going to be like the first step, let's convert it just using using namespaces first, because it's sticking with the IIFE guidelines, because if we use real, like node modules or common JS modules, what we'd have to do is have a module loader, like webpack or System JS or Browserify, and that's a little more than we want to do right now. I'd like to get early wins, and see it running. So we'll just do the IIFEs, and then let's take a look at that controller, and see is, do we want to keep that as a function or we want to turn it into a class.
Reader API Service
We did the module, we did the config, we did the controllers. We did both controllers, now. What's the next easiest? We've got the service and the directive. All right, let's go to the service, that's easier. Yes. So open that up. I'm sure he's going to need himself a namespace as well. Yes. Cool, I'm going to move the Angular part to the bottom, the angular.module. Right, because the service is a good candidate for a class, too. Yes. And we'll make this a class. Yep, class reader api. I like, I like what you, that tip there, where you keep both of them. Yeah, you kind of get to see. When you get faster at it, you'll just overwrite the function as you go. But when I have larger ones, it's kind of nice to see what I was doing. Yeah. So it was kind of an easy way to go about it. Like, it's okay, a contructor, a contructor, yeah, constructor. And you're going to inject http, that'll work. There's an Angular I http. Yeah, it's going to be http. Service-- Service or factory or provider or thing. Yep, and that constructor's doing nothing. That's just to inject it. Now in this one, you don't have to do the, the static http stuff because we're just going to call it dot http. Oh, okay, so I can do the, I can do the public here, right? Yep, do public there, and you automatically get that guy. If I look over here, yes. This, http, so now we're, we can get into these. Exactly, just copy those guys up there. I'll bet you it will be a really simple conversion. So. No more of this. You can do public if you want to. Right. Get rid of the equal sign, and the word, function. Awesome. Reader ID, I assume is, it's a String. Okay, and if you're ever not sure, just put any. Right. Just to get it moving. Get rid of the reviews, and this is going to be a promise. Okay, Angular has one of those as a type 2, so we can do angular dot. It might be dot q, or it might just be iPromise. Let's see, yep, good. So, dollar sign q is in Angular, and it exposes promises. So that's that type that we use there. And then, good, so we're going to return http. But it's not just http now, now it's a property on the class, if you return this dot http. I'm getting an error. I Promise requires a type argument. Oh yeah, because it's got to know what's coming back in the promise. So do the alligators, yep. Like just, any? Yeah, for now that's fine. We could say what exact type is coming out of it, like a String or an Object. And then we'll do return this dot dollar sign http. All right, we'll go in there, we'll check our properties. It's going to want to know the data type of the result in your then. So you see the, then, there? Right. It's saying, hey, what type is that? And that thing has a property called, Data. So just create an Object Literal. Oh, that's like this, right? Yep. Put data. Data colon, just do any. Any. Yeah. Yep. 'Cause you don't know exactly, if you wanted to say, well this is always coming back with a review object, you could create an iReview interface, and then you could say it's returning back a result of iReview interface. If you wanted to. Gotcha. But we can just do any, for now. And this could be a good candidate for a lambda? Yes, that ought to be great there. So you got him into the arrow. And then that way, we're not forced into, I guess with the linter-- You could actually even get shorter. If you get rid of the curly brace after the fat arrow. And get rid of the word, return. And then get rid of the other curly brace. And put it all on one line. Oh nice. And then pull your guy up, and get rid of the semi-colon up there. I think, I'm sorry. The semi-colon after the data. Semi-colon after the data. Yes, now you got a missing-- I'm missing something. Parentheses, you think? There we go. And then that one, maybe two parentheses. Does it show you parentheses matching? Yeah, there we go. Yep, that looks right, it's just white space. Now it's just white space. Yep. Okay, so now you've got your lambda saying, hey, after this is done, we're going to give you a result back in a parameter, and we're going to return the result dot data. And that's just an advantage, so now if you look at the actual code right now over on the right-hand side, it's the same thing we wrote before, it's a function that passes a result and returns result data. Nice. Just a little trimmer. Yeah. Cool. And I notice this stuff here, the string templating type of thing that you can do now. Template strings, yep. It's kind of like this. I'm thinking back to my PHP experience. Yes. You do that, and you have to change the Strings to back-ticks. Back-ticks. So now you're saying, it's an ES6 thing. You're saying, that's still a String, but replace anything with a dollar sign curly braces with a property. Or a variable. So now that'll say, api reader slash whatever reader ID is, slash reviews. Is that the right syntax, I mean look on the right. We can see here it's URL, that plus that. Yeah. Yep. Cool. It's always good to make sure that what you see on the right-hand side is what you expected to see. I keep forgetting to look over there, yep. So let's do the other function now. So I'm just going to, this is probably closer than the other one. Okay. So api readers. Plus it reviews, but it had the same kind of structure with the result data being returned. Okay, and it's called, Reader Info. Get reader info. We're passing in a reader ID, yep. And we still return back a promise of any. Yep. It's a get, it's api reader is reader ID. Good, and the data is the same kind of result, yes. See that's another reason, if you want, we could just use data any, we could do it, like, an I Result up top, if you wanted to, it's really not going to help you much here. We could create something, because we're copying and pasting data, any, multiple places now, so we could just create an interface to do that. Right, yeah, we could get, we could use the schema from... Yes. From the back end and define that. Exactly. As an interface, is what you're saying, gotcha. Yeah, we don't have to keep defining it on the fly. This is just saying, hey, that result happens to have a property called Data on it. Just so that the compiler's happy. Gotcha. Sweet. Let me remove all this other stuff. And I haven't checked the app in awhile. Yeah, let's go see if it still works, man. Okay. If it's getting data, it works, right? It's working, yep. All right. Still getting data. Awesome.
I've been pretty happy with how things have moved along so far. But one thing we got inconsistent on, and I like to be consistent, is we had a Home Controller and an admin controller. And we did injection in a different way. So let's go to, I think it was admin controller. We used the static, so in Home Controller, let's also use static. Okay. Let me copy that really quick. It's the same, exact syntax, right? Yep. And it's the same thing we're injecting. So now, by putting those two lines in, we're declaring the static and the constructor on one line, and we don't need to say, public storage, and we don't need to set the property inside the constructor. So remove that, and just, yeah, looks exactly the same. Yeah, and that's TypeScript in action. It's just making your life a little easier. 'Cause otherwise, you have to say, declare storage, inject storage, and then set the injected storage to declared storage, and this is just saying, you know what, just please set this up for me. So it's a little bit cleaner and easier, and the code on the right should work, and if we go run the app, it should be running, right? Yep. We were in the Home Controller. And then the admin controller should still work. Yep. Wonderful. I think I said, the code on the right, if you're intelligate, but that was reader api, I think. Oh. But yeah, it still transpiled the way it should. Oh right. So you look at-- So the Home Controller, yep, yeah that looks right. Perfect. Cool.
Converting ES5 Angular to TypeScript - Directives
Function Returning IDirective
Type Casting Reader from Scope
So we've got this return object-- Or DDO. Yes, our DDO. Dance Dance Object, Dance Dance Revolution. (laughing) Latest book reviews link function here that's throwing some expected parameter types. Yeah, once in a while, these things are. So scope is an angular thing, so lets do :angular. There's probably an iScope. Yup. Okay. Now, are you using elementer adders? I'm not, so let's get rid of them. If you didn't want to get rid of them, you just do element:ne or you could actually go find the... let's just try it real quick. angular.ielement Maybe it's directive element, maybe it's DOM element. Try DOM element. There's some jQuery, augmented jQuery. Okay. So we can go into him too. So we could define our types, but we're not actually using these though so let's just kill these two guys. We could also do ne by the way. So that's the nice thing about it, until you're not using these parameters, don't bother. So now we've got the iScope in there, and it's still red. What's the red part? Oh, so you can tell what type it is, okay. Just void? Yup. In this case we're not doing anything with the link function, are we? We're not returning anything, no. It's just setting everything up. Okay. So now we've got Scope. Now here's one of the problems. When you've got Scope and it's got properties, one of the reasons I don't use angular iScope is because now notice it doesn't like scope.reader or scope.reviewdata or render reader model. There's a couple ways we can handle this. We can do that same thing before where we make it like the array reference or-- You could do that. Or you can create your own iScope. For example, you can create an ibookreview link scope, an interface, or frankly if you just don't care about that, I would change the Scope to any. 'Cuz you're not actually using any of the Scope functions in this case, you're decorating it with your own properties. And that way you can put the Reader back to being normal. The only thing is that watch. Right, yeah. So in this case, I think any is a good example of a place to use it. Otherwise we'd have to leave the Scope there, we'd have to go create an interface, then we create an interface that's got scope.reader, .reviewdata, .readermodel, .watch ... Let's not go there. It's not getting any value out of it, you know what I mean? It's just being anal for the purpose of being anal. So now we've got a Scope that's any, a function.... do we have any other squigglys anywhere? The function doesn't have a return type. So we'll just make that void. So he's going to be voided. We've got some lambda... Opportunities for lambdas, I like those. And now the data is a parameter, you don't need the parenthesis either. If data is a parameter, we don't need a parenthesis? If it's the only parameter you have, you don't need your parenthesis on that guy. Oh, I did not realize that. If you're going to put type on it though-- Oh, then you need parenthesis? Well go type... What type is it, object? Any. Any looks good. Now you're going to have to wrap it up. Okay. So now you've got something called data that's getting passed in, and it's going to return back to function console.log reviewdata = data. Sweet. And if you didn't have the console.log you could literally just get rid of the curly brace console.log and the last curly brace. You can look over to the right, you're still getting back what you thought you were getting. Gotchya. So you're saying if I got rid of the console.log Scope reviewdata could work like this? Exactly. Yeah, Scope reviewdata, just like before. Yup. Gotchya. And so if you want to keep your console.log you just need the curly braces though, 'cuz otherwise it's not execute both of those. I'm going to keep that in 'cuz that was helpful to debug the scripts for right now. And we've got another lambda down below, we can do that guy. Perfect. So lambdas marked weren't too hard to put together. Nope. So while that's there, want to see if the app is working? Yes. Our directive is still working. It's showing up, that's a good thing. Yup. Alright, there's a couple other options we could do with the directive. Let's go look at the function one more time. So we've got our function inside of our directive, called the "Latest Book Reviews Link". That's pointing to a link function. We could actually make that function be typed if we wanted to as well. So instead of saying function Latest Book Reviews Link function, we could actually do let on that function if we wanted to, we dont have to go here, it's kind of up to you where you want to go, but we could set it up as a variable and then define that link function as a function. Why don't we just do it right above it? Just kind of get an idea. Oh, just do it right above it? Just right below the ngInject. Let's just do a quick let statement. Okay. Do let... just call it link for now. This would be the Latest Book Reviews Link. Make this a type function. Right. And it's a capital "F"' because that's the type in this case. And this would be equal to, and now it's got a parameter list, so this is where your Scope any would go. So would I do function? Nope, you don't need that at all, you just need parenthesis Scope any. So that's your parameter for it. And then do a lambda. And then open-and-closed curly brace. Okay, and you need a semicolon at the end, I think. So what he's saying is you're setting up this function here, you're creating it called Link, and then it's going to be defining a function type, which is going to accept parameters of Scope any. And then what you have in between those curly braces would be all the logic for that-- Would be all this here. Yes. And that's where everything in there would go. And then your link function would actually get referenced there. The reason you've got red... put 'em back, okay you've got it there? Leave that for just a moment. See the return statement? Move that to the bottom of your directive now. Oh, right. Yeah, because it sees that you've already returned him, therefore that let function was no longer valid-- It's not going to execute it. Gotchya. So now you've got to let link unused variable. So if I used it now... Yeah, just leave the first line I think, or comment it out if you want to. So now you've got a link function. And now down here, just call "link". Now link is being used. And now, is that function spelled right? It is. There's some white space between the type. (laughing) That's another thing to turn off, right there. So you've got your function, he's there. And when you compile it on the left, let's take a look... that's not the left, is it? That's the right. Anyway. Left, right, who cares. (laughing) If you look at him, he's got a directive with the link function now. Now see how I did the var link? That's why we had to move all the return and everything else below, because now the link is declared up here, and it's used down below. But now we're actually saying, I mean, I'm not sure we added a lot of value with this, but it's showing you that you can define with let the name of your function, and then you can use it later on inside your code. A few different options. Yup. We're not going to change this, but let's make sure it's working. Let's take a look. But there's one other option I'll show you to look at too.
Directive from a Class
Alright, so we just had a lot of fun with this directive, I'm going to blow your mind. There's yet another way to build the directive. So instead of changing this one around, we went a little off-the-books here and said, Let's just make this guy a function, because quite frankly it was easier to leave him as a function. Right? But we could do a class. So if you could go out the GitHub real quick, I'll show you an example where I created a directive from a class. It's at github.com/johnpapa. Sweet. And then in there, there should be one called Hot Towel Angular Type Script. You're going to have to look for it. Hot Towel Angular Type Script. Yes. That one. So go into the source folder, and then in the client, then the app, then widgets. Those are my directives, and look at the header directive. And zoom in a little bit there. For an old man's eyes. Cool. So notice I did the namespace, but here I use an interface, and the interface is for the Scope. Remember, I talk with the Scope, how we get to find a type? So here I created a Scope type, and then I used that down there on line 24. That way I could do .title, .subtitle, and not worry about all that. And what you did instead was the any, which is perfectly fine. Gotchya. But the real power of this one is on line 16, I used a class, and I said, "Hey, this implements ng.IDirective," just like your function did that. Right, which returns an IDirective, right? Yup. And I have my little inject in there, just to show you that this is where you would do your inject if you inject anything in the constructor of this guy. He doesn't. And then skip him for just a moment. Notice the Scope template are your own restrict properties. Those are the same things you had on your DDO. Now, instead of returning a function, I just use it as properties of the class. They're properties of this class. Now that works perfect, but then when we do line 36, which is directive widget-header, we can't just say, Give the widget-header. We can't just give it the class? No, we have to actually have something that will instantiate that directive. It doesn't work like controllers do. With a controller, we were able to say just point to the name of the class. With a directive, we have to point to the class and then something that will actually create an instance of it. So could you also do new here? Yeah, instead of that we could've done new ht-widget-header parenthesis. Well, how would that work with the dependency injection? Right. That's where it gets a little funky with that. So here, it allows you to define the injecting for the obstructor, your static instance, look into that, and returns that factory method or this instance. Yes. And it's got to be a static instance because you have to be able to talk to it. Because down here, that's just the name of the class. It's not an instance of the class, it's the name of the class.instance. Probably a better name is create instance, I don't know... But it's just another opportunity. This is more class-like. If you look at which code you had on the left still, it's effectively the same thing. You're just using a class instead of functions in functions. You could potentially, I don't know how often you would do this, but extend from base directives potentially? Yeah you could actually make this static instance like a base directive, that it creates a base directive, and then kind of use it for that to get rid of some of the monotony. So that would work.
Compiling the TypeScript Code and Opening in VS Code
So, so far what do you think? We've gone from Angular to Typescript. We kind of had two phases right? We did the environment first where we converted everything over to Use, the typescript compiler, and then we actually converted all the code. How bold are you feeling to see if our typescript compiler works? Oh yeah, let's run the Go commands? The Go commands, yep. Sure. Because, remember we first ran it. It gave us all those errors because we didn't convert everything over yet. Right, so Go Analyze was our winter. Okay. So we had a lot of errors from before, and that is clean now. And it's not having any problems. And if you want to make sure it's actually hitting that, we could also do the TSE compiler. With the TSE-P- -- Client. Client yep, and that'll probably just do it quickly. If we go back into your TSconfig j son, it'll show, we can set the list files to true. And let's make sure it's actually hitting our files, right? Yes. Now that I remember what that setting was. I like that. Sweet, now go over here, run the command again. And now it should tell us here is the file's a hit. It is hitting them. So everything works great. Yeah. Will you do me one last favor? Definitely. I'm a VS code guy. Oh sure. I want to see if you can open the same project in any other editor. Certainly I do have that installed here. Yeah I did make you get it. (laughter) This is the same app. This is the same app. This is the admin controller. Okay. TS. And we have the intellisense here. If you hold the command key down on top of that, it shows you the peak. Great and let's go to the service for a minute. Okay. So inside of here, if we went inside of the services, let's see, like part of our ACTP for example, hover over the IHTP service. It gives you the types, shows you all that, we could actually dive into the definitions. So it's showing you that what we did is not specific to intelliJ. It's, you really could use a web store of intelliJ. Sublime, VS Code, Adam, you pick. Right. Right? So it works pretty good. Yeah, yeah, this wasn't too bad. And we could do it in phases as well. We could, at the start we just-- Right. Named the GS files to TS files. We could use NEs all over the place if we want. Yes we can. And then yeah, working those typings as we needed. Exactly, and now you can power that, as you got a really large project, right? You can convert as you go, and notice how we checked the project along the way to make sure it doesn't still work. So you've got that little litmus test. Now what I probably would recommend is in larger projects, you do commits, right? Getting committed, push this up as you're, when things work, push them. Right, yep. You know. Have some unit tests too to make sure that the-- Unit tests would be good. I mean, we could save that for another day. Definitely. Converting all the unit tests. But I think things are pretty good. Yeah. I hope you had some fun. I did, thank you very much for walking through this. Thanks Chris, appreciate it. Thank you.
Released1 Apr 2016