What do you want to learn? Leverged jhuang@tampa.cgsinc.com Skip to main content Pluralsight uses cookies.Learn more about your privacy Practical TypeScript Migration by Steve Ognibene This course teaches practical techniques for migrating existing projects from JavaScript to TypeScript. Start CourseBookmarkAdd to Channel Table of contents Description Transcript Exercise files Discussion Learning Check Recommended TypeScript Introduction Introduction Hi, my name is Steve Ognibene and welcome to Practical TypeScript Migration. This is course is designed to help people with existing JavaScript code bases learn how to migrate their projects to TypeScript. If you've heard about TypeScript, but aren't sure how to get started, this is the course for you. We're going to talk about what TypeScript is and what it isn't. We'll take a real working JavaScript game that uses everyday libraries like jQuery, Knockout, and QUnit, and convert it to TypeScript start to finish. Then we'll do some refactoring work to improve the project's code so you can see what the developer experience is really like once you've converted the TypeScript. Finally, we'll implement a simple build script using Grunt and other packages from NPM that run on Node.js. All through, I'll try to offer practical advice regarding the TypeScript migration techniques that I've found to be effective. What do I mean by practical? That's a rather qualitative word, sounds like something a politician might say. Well, what I mean is that in this course, I'll teach you the techniques for moving things over to TypeScript in such a way that the key benefits become available to you while minimizing or avoiding some of the downsides. When TypeScript makes something awesome, I'll be sure to call it out, and when TypeScript makes something difficult, I'll be sure to tell you that too. I want to make sure you're prepared to face the TypeScript you'll see in the real world. There are three prerequisites to get the most out of this course. First, I'll assume that you're somewhat familiar with coding in JavaScript, if not, you'll probably want to check out an introductory JavaScript course on Pluralsight first before watching this one. Second, I'll assume that you have basic familiarity with an object-oriented and strongly-typed compiled language like Java, C++, C#, or VB.NET. For example, I'm not going to explain what a class is or what an interface is so if I've just blown your mind with those words, you may wish to watch the TypeScript Fundamentals course on Pluralsight first because it gets into the basics in a lot more depth, then come back. Finally, I'm going to assume that you're comfortable using the command-line. Pretty much if you can switch directories, understand relative paths like dot dot means the parent, and running commands, you should be fine. This course doesn't require the viewer to have already used TypeScript, however, it doesn't offer comprehensive coverage of the TypeScript language, for that, I would recommend checking out TypeScript Fundamentals by John Papa and Dan Wahlin. This course also won't cover anything having to do with Angular, at least not directly. For a course tailored to the details of using TypeScript with Angular, check out Justin Schwartzenberger's course, Using TypeScript for Large AngularJS Applications. I'll be using Visual Studio 2013 Professional, Update 4, as my IDE throughout this project. That's a paid product, but Visual Studio 2013 Community Edition is available for free from Microsoft and it supports everything we're going to use in this course. You could also use WebStorm, Eclipse, or any other text editor. A TypeScript plugin is helpful, but not required. If you like open source tools, a particularly excellent TypeScript editing experience can be found in the Atom editor if you install the new atom-typescript extension by Basarat Ali Syed. I'll also be using Windows for this course, but that's not required either. TypeScript is a multiplatform system and works great on Linux and Mac too. Everything we're going to see in this course can be accomplished on those platforms with minimal changes just due to not having Visual Studio. If you're going to be using an IDE or an editor with a good TypeScript plugin like atom-typescript, you should be able to follow along with the workflow perfectly well. If you're more of a compile from the command-line type, you might want to watch the final module first where we set up the build script. That build script will serve you well when you return to the first part of the course. If you're using Visual Studio, you might be best served watching it straight through. The final housekeeping thing I want to make clear is that the Coin Counter sample app we'll be migrating is written entirely in HTML, CSS, and JavaScript. There's no server side stack that we'll be using. One of the goals with this course was that it should be equally valuable to developers using ASP.NET, PHP, Ruby, Express, or whatever your favorite web framework is. Let's talk a little bit about what TypeScript is and what it does. The TypeScript language is a superset of JavaScript. People like to say that being a superset means that any valid JavaScript code is also valid TypeScript code. This is technically correct with the qualification that TypeScript reserves the right to tell you if it thinks the code you've written is wrong. TypeScript is a compiled language. It takes a set of input files, runs them through the compiler, and produces a set of output files along with a list of errors. If you're doing this process manually, you'll use a TypeScript Compiler, or TSC. If you're using an editor that supports TypeScript like Visual Studio, your editor will call into either TSC or something called a TypeScript language service and you'll just see the results. This is very different than JavaScript where you just save the file to disk and it's ready to go. I sometimes hear people say that TypeScript adds a type system in the JavaScript. I disagree with that somewhat. JavaScript definitely has a type system, it's just entirely dynamic. It's got numbers, Booleans, strings, functions, objects, and arrays. There are very specific rules for how JavaScript works with types at runtime, for example, you can take a string, and add a number to it, and the result is a string. In my opinion, that's a type system. One of the key things that TypeScript gets right is that rather than inventing something new, it embraces the existing type system in JavaScript. TypeScript makes excellent use of type inference. It determines something's type from how it was instantiated. This means that developers can enjoy the benefits of strong typing without having to explicitly declare types on everything. If TypeScript can figure it out, you're good to go. TypeScript strikes a great balance between encouraging you, but not requiring you to declare types on things like function arguments where the types help document how your code is meant to be called and, for example, not having to declare a function return type where they can be inferred. TypeScript also lets you use a virtual slider bar for how strictly you want it to check your code. If you want TypeScript to provide warnings only and emit the compiled JavaScript as long as there aren't any blatant syntax errors like mismatched parenthesis, that's possible. If you want TypeScript to prevent compilation of your code altogether if there are any type errors, that's also possible. TypeScript even lets you decide on a per variable basis if you don't want any type checking at all, just declare it with the any type. If you declare a variable to be of type any, then you can assign it any type of value that you want and TypeScript will raise no errors. This is great for sections of code that are highly dynamic in nature. So what's the runtime cost of all this strong typing? You may be surprised to find out that it's essentially 0. When TypeScript compiles your code to JavaScript, one of the major steps is type erasure. This really knocked me out the first time I heard it, but it makes sense. TypeScript is all about compile time enforcement of types. If the types in the code are correct at compile time, then they should be correct at runtime assuming things are called in the way that the TypeScript code indicated. So TypeScripts with strong typing is just a development time concern, not a runtime concern. That makes me wonder, what's the development time cost? This is something that you'll have to evaluate for yourself. Getting started with TypeScript definitely has a non-0 upfront cost. Just for starters, you're spending time right now watching this course instead of coding in JavaScript. Occasionally, you'll fight with the compiler when you either don't know how to type something, or even worse when you can't type something without type something without resorting to using any. We'll hit one of those instances in this course. The type definitions you download for an existing JavaScript library may not agree with how it's actually implemented, or maybe for a different version, and this can cause situations where TypeScript won't allow you to enter code that you know to be correct. All these things have workarounds and we'll cover some of them in this course. One of the things that really isn't workaround-able though with TypeScript is that there's a compile step. On my i7 laptop running the command-line TypeScript compiler on a 2-line file takes about 0.8 seconds. Compiling the final version of the project in this course including full definitions for jQuery, Knockout, and other libraries, takes about 1.3 seconds on that computer, about half a second difference. So you have to decide whether waiting a few seconds every time you want to run your app to ensure it's correct is better or worse than having to write more documentation and more unit tests. Or even better, use one of the editors like Visual Studio or atom-typescript that keeps the TypeScript language service in-memory and compiles as you code. This can reduce the JavaScript emit time to a fraction of a second. Now my favorite benefit of using TypeScript that doesn't get talked about enough up front is how easy it is to refactor. Erich Gamma gave a talk at Build in 2014 where he said, "You can write JavaScript code fast, but you can't refactor JavaScript at the speed that you write it." I think this is absolutely true and it's one of the reasons that working big JavaScript code bases is difficult. The TypeScript refactoring experience is excellent. TypeScript tests several features that we're used to seeing in other strongly typed languages, like safe rename, or find all references that worked reliably across files, or warnings if we haven't implemented a mandatory property on an interface. So much more of our time as developers is spent maintaining code and reasoning about code than spent writing new code. How many times have taken several hours to fix a bug and the source control check-in was like one or two lines? Having a tool like TypeScript that can statically analyze our code better than the human mind is capable of doing frees your brain to concentrate on solving the truly hard problems that computers can't. The final thing I want say about TypeScript is that it has helped me become a much better JavaScript developer. TypeScript embraces coding concepts that will be available in ECMAScript 6, the new standard for JavaScript coming out in 2015. The cool thing is that the JavaScript code emitted by TypeScript is perfect readable and I found it really educational to think hmm, why did they emit it in this way versus this other way? I really like that I could write simple code simply and TypeScript will handle the prototypes and iffys for me. If I didn't like how TypeScript wrote it, I'd copy the code and do it myself. Okay, I know that there are several projects that I've done in the past two years that I wouldn't have been able to deliver as fast or as well without TypeScript. If you work in a team or if your project is bigger than trivial, I really can't recommend it enough, but words are cheap you might say, show me the code. Okay, let's do it. In this next module, we'll take a look at an existing JavaScript app called Coin Counter. It's a game, but it uses all sorts of JavaScript libraries typically found in business web apps. We're going to embark on a practical TypeScript migration. By the end of this course, the entire app will be in TypeScript and we'll have a starter Grunt build script that runs on Node.js. Are you ready? Here we go. The First Conversion A Tour of CoinCounter Welcome to module two in Practical TypeScript Migration. This is where we'll convert our first block of code to TypeScript. Before we dive into migration work though, I want to show you the Coin Counter sample application and talk to you about its makeup. Let's get started. I loaded up the module 2 before code in Visual Studio 2013. Throughout this course when I want to launch the project, I'll use the Ctrl+F5 key combination to launch the website in IIS Express without attaching the Visual Studio debugger. This will allow me to debug using the browser's F12 tools if I want to. Coin Counter is a simple game designed to help children learn to count change. The code that I provided includes artwork and monetary values for US coins, but the game could very easily be adapted to any local currency. I'll type my name and press Enter. The game clock starts ticking down and I've been asked to make a certain amount of change. I'll try to do that. Sixty-six cents, quarter, quarter, dime, nickel, penny. Correct! As you can see there's code to handle button clicks, draw pictures of the coins, display success or failure dialogs, and track your scores versus a high score list. I'll click that. I'm not on here yet, Alice, Bob, and Charlie. We'll go to Game and click Resume. It'll count down for the final four seconds. Great, that's #3. I'll hit Close, High Scores, sure enough, I'm down there. I have to say though that my favorite feature of this game is the unit tests. I'll go ahead and do that. This will launch QUnit, which will go through and run the 26 assertions that we set up. Let's talk about how this game is put together. CoinCounter's Design The Coin Counter game is implemented entirely with HTML, CSS, and JavaScript, and it takes advantage of a number of open source libraries. The data-binding functionality is provided by Knockout.js. We're using data-binding expressions embedded in the HTML, as well as Knockout observables and computeds in our JavaScript view model. We're using Bootstrap to get nice styling and a responsive layout. Coin Counter uses big.js to do accurate arithmetic on decimal numbers. That's important because the floating point number type built into JavaScript can't do that without rounding errors. We've got jQuery on the page to support Bootstrap, and for a few miscellaneous chores, and finally we're using QUnit for unit testing functionality. We'll see these libraries being used throughout this course. I'm not going to spend a great deal of time covering their functionality, except where it's relevant in Coin Counter or when it might apply generally to a TypeScript migration project. You might see enough to wet your appetite though and I'm pleased to say that there are other Pluralsight courses that cover each of these libraries in depth. Let's talk about the Coin Counter project structure. It's got two HTML files, index.html, and test.html, there's also coincounter.js. That's one big JavaScript file with all of our game logic in it. Then there's our collection of third-party libraries. Index.html references everything but QUnit, which is our testing library, and tests.html references everything but Bootstrap, which is our responsive layout system. Lastly, the tests.html file also references the gametests and gameclocktests JavaScript files. When planning a TypeScript migration, we need to have a pretty good understanding of the layout of the code base that we'll be converting. This will help us identify what parts to convert first and what parts, if any, we should put off until later. With this in mind, let's zoom in a bit on the structure of Coin Counter. There are four main objects defined within the coincounter.js file, app, coins, GameClock, and the CoinCounterViewModel. This already gets me thinking, since the contents of the Coin Counter file are already broken out into discrete parts, we may be able to migrate each of the components separately. Let's look at each in turn. It seems that app is just an object literal with some configuration for the application. It looks pretty simple and I'll bet these settings are used throughout the rest of the code. Hmm, it's very simple and it's used in other places. Let's keep that in mind. Coins is an array of object literals that has simple properties, as well as properties that use the big.js library and Knockout, a touch more complex, but still fairly straightforward. GameClock is definitely starting to be a bit more complicated. The function that captures this, and adds properties to it, looks like a class to me, but in the JavaScript functional style. It uses Knockout observables and some things not pictured here like callbacks for when the timer elapses. Next, there's CoinCounterViewModel itself. This block of code uses all three of the previously discussed components, app, coins, and GameClock, and is responsible for basically everything in our game. Hmm, responsible for everything, possible refactoring target? Let's keep that in mind for later too. Finally, there's a small amount of miscellaneous code and the unit tests. Choosing a Conversion Candidate So let's talk about what makes a good first candidate for a TypeScript migration. We're going to try to be really practical about this to make sure that our first conversion is successful. I'd say the first thing to look for when you're getting started is to try to find something that's short. Some JavaScript code converts into TypeScript exactly as is, other code might need some refactoring in order to play nice with the type system. For your first conversion, if you pick a block of code that's short, it won't matter which kind it is. This is as opposed to selecting a block of say a hundred lines of code, there might be a dozen things you need to fix in there. Try to get some success with something short before trying to convert something long. Similarly, it's great to choose something simple for your first conversion. You should fully understand what the code is doing. After you get some success converting code that you understand what it's doing, then you can worry about all the code where you don't understand what it's doing. Another attribute of an ideal first conversion candidate is something that's referenced a lot by other code in your project. Types in TypeScript flow outward from the reference code into the referencing code. If you convert some code that other things depend on, the types you setup will help you when you convert the dependent things later on. If you use JavaScript unit tests, choosing code that has tests for an early conversion candidate is great, however, for the very first migration it's possible the thing you'll convert is so simple that it doesn't require tests at all, that's fine too. Next, if you can find code that is somewhat self-contained, it's helpful, though this is not strictly required. TypeScript has some great refactoring capabilities that will help you improve the modularity of your code after everything's converted. Finally, your first conversion candidate should be something that you own. This is a bit of a soft criteria, and what I'm trying to say here is that we want to be sure that if we convert something to TypeScript we have enough control over it to keep it as TypeScript, unless we decide to revert it to JavaScript. If there are parts of an application that you're in charge of, and parts that you're not, choose a part that you're in charge of. As part of planning our practical TypeScript migration effort, I've written up a conversion worksheet. Each of the conversion candidates are listed with the approximate lines of code and a relative level of complexity. I've also noted how much each thing is referenced by other code in the project or even other parts of itself. Finally, I've specified if something has unit tests or if the thing is a set of unit tests. For our first conversion, we're mainly looking for something that is short, simple, self-contained, and referenced often. If unit tests are available, that's a bonus. We own everything in this code base so ownership is not a consideration. When we eliminate the items that are of medium or high complexity, we're left with app that's referenced throughout our code base and these two miscellaneous items that aren't referenced much. Since it's best to choose something that's referenced often, I think the choice is clear. So our first conversion will be app. It's short, simple, self-contained, and referenced often. It doesn't have unit tests, but it doesn't really need them because it's basically just an object literal. We've chosen our first conversion candidate carefully, so hopefully we'll have some success that we can build on when we do the next conversion. The First Extract and Conversion I've opened coincounter.js in Visual Studio 2013. We've decided we want to start our TypeScript migration with the app variable in Coin Counter. In order to convert just the app variable to TypeScript, I'll need to extract it to a new file called app.ts. I can just right-click the project in Solution Explorer and choose Add, TypeScript File, and this is what we'll do later in the course, but for now, I just want to show the experience of converting a JavaScript file to TypeScript, so I'll choose Add, JavaScript File instead, I'll name it app.js and copy the app variable definition from Coin Counter into the new file. I need to add var to ensure it's properly declared, and next I'll remove the declaration of app in the existing JavaScript file, clean up the empty space, and save everything. Finally, I'll need to add a reference to load app.js wherever it's needed. In our simple game that's in the bottom of our HTML files. JavaScript loads and executes in page order, so I'll reference app.js before coincounter.js, that way the app global variable will already be there when it's referenced inside Coin Counter. Next, I need to add app.js to the tests.html. I'll save again. Let's run our test just to make sure everything's still good. (Running) Great, we're still green. Please note if you have trouble distinguishing color, QUnit puts a checkmark up in the title bar if everything passes. If not, it shows an X. I'll use the term tested green throughout this course, but what I really mean is that they're all passing, and you can tell by looking for the check. We've now extracted a file called app.js from our original coincounter.js. For you web optimization folks that are thinking, oh no, another HTTP request, don't sweat it, we'll optimize our JavaScript delivery later in this course. For now, we're focused on modularization. So, let's go ahead and finally convert app.js to TypeScript. This is very involved and complicated process, so pay close attention to this part. We're going to right-click the file and choose Rename, then I'm going to change the .js to a .ts, and hit Enter. Visual Studio very helpfully explains to me what a file extension is. Thanks Visual Studio. Yes, in fact, I do want to change that extension. The first time you create a TypeScript file in your project, Visual Studio will also ask you if you want to go up to NuGet to search for library definition files. We'll definitely want to do that later, but it's not necessary for now, so I'll click No. And that's it; we've got a TypeScript file. Let's open it up and take a look. Once a TypeScript file is created, you'll see this split screen view if you have Web Essentials installed. In the view, the code in the left hand pane is the TypeScript, and the code right hand pane is the emitted JavaScript. The split bar can be moved horizontally, and most of the time you'll probably have it completely stowed to the right. Since you haven't saved your TypeScript yet, Web Essentials warns you that there isn't any JavaScript compiled to disk yet. I want to advise you about a bug with Visual Studio 2013 in TypeScript. This bug is present with TypeScript 1.3 or 1.4 and may occur with earlier versions as well. Visual Studio doesn't completely initialize the TypeScript functionality for files under certain circumstances. This means that the compile on save feature and automatic references between TypeScript files in your project may not work correctly. The workaround is to unload the project, and then reload it. The bug can be reproduced when you initially rename a file's extension from .js to .ts, which we've just done, or when you download a definition file from NuGet. The TypeScript Team is aware of the problem and it should be fixed in a future version. This is pretty annoying even though there is a workaround because reloading a project closes any open files and you'll lose your place. A better workaround is to use a macro runner in Visual Studio 2013 to handle the project reload for us. The macro system was removed in Visual Studio 2012, but the free Visual Commander extension restores this functionality. I placed a tinyURL here pointing to the Visual Studio Gallery website, or you can install it by the Extensions and Updates menu in Visual Studio. Once you've got Visual Commander installed, you'll need a project reload macro. I found one written by Sam Saffron on Stack Overflow and modified it to work with Visual Commander and VS 2013. You can find it at tinyurl.com/reloadmacro. I've already got Visual Commander installed, but I want to quickly demonstrate adding the macro. Open the VCmd menu, click Commands, and then Add, name the macro something like Quick Reload, then copy the code from GitHub, you may find it easiest to click the Raw button first, we'll copy it, delete everything and paste it in, then click Save and Compile. As long as you see Success, then you should be good to go. I'll close this. Now there should be a Quick Reload option at the bottom of the VCmd menu, I'll click it. The macro will unload and reload the project of the currently active file, it also conveniently remembers which files were open and where the cursor was located in each. Now that we've covered the bug in Visual Studio, let's remind ourselves where we left off in this first TypeScript conversion. We started with a high level assessment of Coin Counter and decided that the app component made the most sense to convert first. Then we created a new file called app.js. Normally you'd just create a .ts file, but I wanted to make sure we hit the bug with renaming files so that I could show you the workaround. Then we copied the app code from coincounter.js into app.js, then we renamed app.js to app.ts, this triggered the bug. From now on, all we have to do is use Visual Commander to reload the project and the bug will go away, being that compile on save should work properly. I think we're ready to see this thing compile. Off camera I closed all the files, so I'm going to open up app.ts again, make a trivial change like adding a space, and then click Save. Exciting! The right hand pane is now updated with the JavaScript code emitted by TypeScript. It's not just in the Web Essentials panel, it's on disk too. In fact, if I select the project and click the Show All Files button, you can see I've got a new app.js here. So now we've got an app.js again, except this time it was generated by TypeScript after compiling app.ts. You may notice that the emitted JavaScript is essentially identical to the original code, except that the TypeScript compiler added a source map entry. This is great! It means that in general, the JavaScript code emitted by TypeScript will make sense to us and resemble the code we wrote. This is possible because any valid JavaScript code is already valid TypeScript code. TypeScript just adds some extra syntax that is either compiled to normal JavaScript or simply erased after the compile step. So how did Visual Studio know to compile our TypeScript file on save, and why did it choose to generate a source map file? In a Visual Studio web project, the configuration for TypeScript lives in the project properties in a new tab called TypeScript Build. We'll explore that tab in the next clip. Visual Studio TypeScript Build Properties Let's check out the TypeScript Build properties by right-clicking on the CoinCounterGame and choosing Properties. Once TypeScript is added to your project, the new tab appears down here. Let's discuss some of the most useful settings in the TypeScript Build tab. Our app is intended for modern browsers in early 2015, so we can safely choose ECMAScript 5. ECMAScript 3 is a better choice to support IE 8 and below, and ECMAScript 6 will be a good choice in probably a year or so, unless you're doing something more advanced with a post-processor like Tracer. That's out of scope for this course. You can see that the default is to have Visual Studio compile TypeScript files on save. This if fine while we're getting started. Right below that is the Allow implicit any option. In order to understand this important feature, we need to first understand type inference. TypeScript tries to infer the type of variables upon declaration. So for example, if I write var x = 1, TypeScript will infer that x is a number and treat it that way throughout its scope. I don't have to explicitly tell TypeScript that, the language service just figures it out. I then put var y = x + 1, TypeScript would infer that y is also a number. Finally, if I added var z = x + thing, TypeScript would infer that z is a string, this is because if you append a string to anything in JavaScript, the result is a string. So you can see how in TypeScript types can be inferred from how a variable is initialized. So what happens if we don't initialize a variable when it's declared? Var x, x = 1. In this situation, TypeScript does not infer the type of x, or rather it infers the type to be any. Any type in TypeScript is a type that allows a variable to behave just like a regular JavaScript variable, meaning it can accept anything and the compiler won't reason about its type. When Allow implicit any types is enabled, which is the default, TypeScript won't warn you if it's not sure what type the variable is, it will just implicitly say, well, I'm not sure what type this thing is, so I'm just going to make it any. That's fine if you're getting started, but it doesn't really help us understand how TypeScript is interpreting the types in our code. In general, I recommend disallowing implicit any types. It can be a bit more work initially to get a TypeScript code base that was converted from JavaScript compiling without errors, but I believe that disallowing implicit any types ultimately helps improve your code quality. This is one of the project-wide decisions you'll have to make with your team. You can certain plan to enable it later, but don't wait too long. We'll disallow implicit any types in the Coin Counter project. Continuing in the settings dialog, we're not using external modules, so we can leave this setting alone. If we were using external modules, we'd want to select CommonJS for compatibility with Node.js, Browserify, or webpack, or AMD for compatibility with RequireJS. Finally, there's more options related to how and where the JavaScript is generated. We can choose to erase comments from the emitted JavaScript if we want, and we can see why TypeScript created a source map for our app.js since the source maps option is enabled. Now that we've covered the TypeScript Build options, let's see what TypeScript thinks of our app variable. I'll flip back to app.ts and hover my mouse pointer over app. In the tooltip, we can see that the TypeScript language service has identified the interface of app, TypeScript knows it's an object literal that has several string and number properties on it, and TypeScript even sees that there's a starterHighScoreList, which is an array of object literals that have a name and score property. You can tell it's an array type because it shows the open and close bracket on the end of it. How did TypeScript figure this out? Don't I have to manually assign types to everything? Isn't this supposed to be more painful? Well, a key feature of TypeScript is type inference. As we said earlier, in TypeScript, types flow from where they're declared to where they're used. Since we've instantiated app when we declared it, TypeScript infers its type from that and then will persist that type throughout the code wherever app is referenced. If we were to type app. at the bottom of this file, we'll see that Visual Studio is able to identify the app members that starterHighScoreList is an array, it has a normal JavaScript array and members available, that if we select an element in it, the element has a name and a score property, and that the score property is a number. Now, the Visual Studio JavaScript IntelliSense engine is pretty good and would actually be able to do that much too in plain JavaScript, but later on we'll see that the TypeScript language service is able to flow these types out into other files where app is used as well. I'll remove our test code and save the file. What do we do now that we've migrated a file in our project to TypeScript? The dev in me says migrate more files to TypeScript, more, more, more, but the team lead in me says hold on, this is a bit of a milestone, let's pause for a moment, and think about what we've done. Don't forget this course is called Practical TypeScript Migration. There's a few things we need to straighten out before we continue. Preparing Your Team for TypeScript Let's talk about the practicalities of using TypeScript. For teams that use Visual Studio as their one and only IDE, having everyone on the same Visual Studio version and even the same Visual Studio update, becomes really important. The version of TypeScript that you'll use is somewhat strongly tied to the version of your Visual Studio IDE. In addition, it's important to standardize in a particular TypeScript extension version. As of March 2015, TypeScript 1.4 is the latest released version and it's what we're using this course, 1.4 is available as an extension in Visual Studio 2013 and it's included with Visual Studio 2015 CTP5. TypeScript 1.3 was included with Visual Studio 2013 Update 4; 1.0 is available as an extension in Visual Studio 2012 and it was included in Visual Studio 2013 Update 2. The TypeScript 1.1 release was basically a fully compatible rewrite of the 1.0 compiler that dramatically improved its performance. It wasn't ever included in a Visual Studio release, but it is possible to manually overwrite the 1.0 compiler with 1.1 to get the extra performance. In case you're wondering, there wasn't a TypeScript 1.2. That's a lot of versions. Which one should your team use? Well, I think the best thing you can do for a new project is to start with 1.4 if you can. The 1.4 release added union types and type aliases, which are a major language feature for library definition authors. In fact, many third-party definitions now require 1.4. If you can't use 1.4 for some reason, 1.1 or 1.3 are fine, the major downside is that you may have to search for older library definitions. If you're already using TypeScript on a project, stick with whatever version of the compiler you're already on until your team is ready to dedicate some time to upgrading to the latest. The time necessary to upgrade is usually spent fixing any compile issues that come up and re-testing the emitted JavaScript. Let's talk about source control. One of the best ways you can smooth your team's transition to TypeScript is by not including converted JavaScript files in your Visual Studio projects anymore, and also not checking in those files to source control. Think about it, if you work on Visual Studio projects that compile down the .dlls or .exes, you don't check the compile binaries in the source control, they're simply deployment artifacts. By that logic, why would you check in an emitted JavaScript file that was compiled from TypeScript? It's basically the same thing. Now don't get me wrong, I do recommend keeping an immutable record of stuff that gets deployed, but what I'm talking about is if a developer makes a change to a TypeScript file, compiles it, and it tests out okay, then they should only check in the TypeScript changes and not the corresponding JavaScript and map files. This makes your source control history cleaner and prevents developers from accidentally checking in JavaScript that they edited directly without a corresponding change to the related TypeScript file. In my own experience, I messed that up a few times before implementing this rule. Another team-related topic is what to do if there are developers on the team who are opposed to migrating toTypeScript. I've heard many arguments against TypeScript since it was announced. Some of the more reasonable ones are: I don't want to wait for a compile step, or I don't want fight with a type checker, I'd rather everything just be dynamic. There are a few tips that I can offer to team leads who want to migrate to TypeScript for how to handle developers who are happy with regular JavaScript and don't want to change. The first tip is to try to nominate areas of the application that will remain as plain JavaScript and keep the skeptical developers working only on those areas. Depending on the size and complexity of your code base, you may not be able to migrate all of the TypeScript quickly. In fact, you may decide to limit the scope of your initial migration for a set time, this idea would hopefully keep the JavaScript-only folks productive while the rest of the team gets comfortable with TypeScript and begins to experience its benefits. Over time, you'll hopefully be able to expand the TypeScript zone and include more of your developers. The second tip is to have an easy and fast build step. If you're using Visual Studio's TypeScript build system, make sure you've got TypeScript 1.3 or higher. The compilation speeds are much faster. They're not joking when they say it's four to five times faster, it really is. If Visual Studio's TypeScript build system doesn't meet your needs, we'll take a look at grunt-ts in a later module, that should cover most any build requirement. Having the build easy and fast will make everyone more productive and will hopefully mitigate people's concerns about the TypeScript compilation steps slowing them down. The third tip is to offer an escape hatch. One of the things I like best about TypeScript is that the emitted JavaScript looks very close to the developer's original code. It's always an option to start your TypeScript journey by saying something like, let's try TypeScript for 30 days or 2 sprints or whatever length of time, if we decide we hate it, we can just delete the TypeScript files, we'll change our source control back to check in the JavaScript files again, and we'll be back to work in no time without having to reverse integrate all of our work. With a prearranged back-out plan, people are sometimes more willing to take a leap than they would be otherwise. I would say that the fourth tip is to use positive peer pressure. Assuming that you're actually having success with TypeScript, be sure to share that as much as possible, but be careful here, try to make it about your experience and how TypeScript helped you, don't make it sound like a lecture, or power play, or try to tell others what they should think, try to use a lot of me and we words and not you words. Most developers who hear good things about a technology from people they respect for a long enough period of time, will eventually be willing to give it shot. That's enough about teams for now. Let's convert some more code to TypeScript. Converting GameClock I'm looking at the list of conversion candidates that we wrote up before and I've checked the box next to app. I love making lists and checking boxes. Even though what we've converted so far is simple, we've begun to make progress and we've finished a self-contained unit of work. For our next conversion, I'd like to take on something slightly more complex. A good second candidate will still be fairly short in length and simple conceptually. Ideally, it will reference the first thing we converted. Icing on the cake will be if the conversion candidate has unit tests, that way we can be sure that the code's functionality is still working correctly after the conversion to TypeScript. As before, it's best if the code is somewhat self-contained, and that you or your team have ownership of its direction. Looking back at our conversion worksheet, I think that GameClock is a strong choice for our next migration. It's a bit longer than app and somewhat more complex, but not too bad. Also, while it isn't pictured here, the code for it is already quite self-contained so it should be a good refactoring target, plus it has unit tests so we can quickly tell if we've broken anything after changing it. I've opened coincounter.js in Visual Studio again. GameClock is already pretty much self-contained, so I'll just add a new TypeScript file called gameclock.ts, and cut and paste the GameClock function. Then I'll remove the declaration of GameClock on the other file, and add it to the new TypeScript file. Immediately, we see some red squiggles. This is our first encounter with the TypeScript type engine. I'll open up the error list to see what's going on. I'm also going to sort the list by description. It seems that we've got four implicit any errors, that's fine, we signed up for that by disallowing implicit any types in the project's TypeScript build properties. The other three errors are telling us that TypeScript isn't able to find a declaration for the ko variable. That's the global variable used by Knockout.js. Let's fix the implicit any errors first. Right up top, we can see that the function arguments are underlined. It's generally useful to provide types explicitly to function arguments, it helps people understand how the code we're writing is supposed to be called. InitialTimeInSeconds is supposed to be a number, so I'll add a type annotation for that with a colon and type number. We can see that the error goes away. Now we're down to six. Callbacks are typically functions that return void. I could specify Function with a capital F as a type and that would clear the type error, but it's better to be more specific if I can. A good way to do that is by using the TypeScript fat arrow syntax. I know that our callback is a function that takes no arguments and returns nothing, I can represent that as an empty set of parenthesis for no arguments, and draw a fat arrow for returns, and put type void. The thing we're passing in to GameClock is a reference to a function that accepts no parameters and returns void. Next is intervalHandle. I'm not assigning a value to intervalHandle right away when it's declared, so TypeScript wants me to explicitly type it. I have no idea what it should be, how would I find out? Well the easiest way is to just let TypeScript tell me. It looks like we're assigning a value to intervalHandle on line 10. The variable is assigned the result of the JavaScript setInterval function. If I hover my mouse over setInterval, the tooltip tells me that setInterval is a function that takes some stuff and returns a number. How about that? So let's use number for the type of intervalHandle. I'll go up to where intervalHandle's declared, assign type number, and the error goes away. How did TypeScript know that setInterval returns a number? Well, over the last several years, the TypeScript Team did a ton of work explicitly typing out all the standard JavaScript objects and functions, as well as all the objects and functions available in the browser's DOM. This hadn't ever really been done before, at least not in a programmatically accessible way, and it's one of the most useful things about TypeScript. The documentation for JavaScript in the DOM's interfaces are provided in a TypeScript definition file that shifts with the language. If I right-click on setInterval and select Go to Definition, you can see that it brings me into lib.d.ts. There's over 14,000 lines of definitions in this file that help TypeScript developers understand their environment better and not make mistakes. I'll close lib.d.ts. Let's clean up this last implicit any error and then we'll get onto the Knockout issue. I'll double-click the error and type the parameter numberOfSeconds as a number. That fixed it. Now we're just left with some instances of Cannot find name ko. Ko is the global variable that Knockout.js uses. It's similar to how jQuery uses the dollar sign. How should we fix this issue? First, let's look at how might fix it ourselves just to learn the basic technique. At the top of my file, I'm going to create a new variable called ko, and type it as any. Oh, that fixed it; I guess we're done here. Well, maybe, this is a perfectly valid way to eliminate these types of errors, but it doesn't enable TypeScript to help you by checking that you're calling your code correctly. When TypeScript sees an any type, its language service behaves like regular JavaScript would and it simply assumes that you know what you're doing. It's nice to know that the worst case scenario when you're working with TypeScript is that your code will basically just behave like JavaScript. Well that can be good enough, and it's certainly a valid way to fix problems, especially while you're just getting started. Let's see how we can do better. I know that Knockout is an object, but I don't have to call new on it to use it. The ko variable automatically gets defined globally, as long as I'm referencing the Knockout JavaScript file. Since I know that, I can declare ko as an empty object literal. You'll notice how TypeScript seems to be fine with the variable ko existing now, but it's warning me that the properties observable and computed don't exist on it. Okay, let's fix that. Inside the object literal definition, I'll define a property called computed and a property called observable, both as type any. Now TypeScript is happy again. It knows that ko has two properties, one called observable and one called computed, that are explicitly typed as any. If we wanted to continue building out this definition, the next step would be adding more properties to ko along with more explicit types. We could do that, but rather than build out a definition for a popular library ourselves, wouldn't it be nice if we could use a definition that was already created and validated by a team of TypeScript experts? Well it turns out that we can. On GitHub, there's a project called DefinitelyTyped that contains definitions for nearly 700 JavaScript libraries as of January 2015. This project was started by GitHub user Boris Yankov on October 5, 2012, 4 days after the initial TypeScript announcement on October 1. Within a day, Boris Yankov put together basic definitions for seven popular JavaScript libraries, and within the first week the project grew to 11 libraries and accepted its first pull request. These days, the project accepts many pull requests per week and releases individual library type definitions via NuGet or a custom MPM Module called TSD. Let's fetch the Knockout definition from DefinitelyTyped via NuGet. First we'll remove our attempt at manually typing ko. As expected, our type errors come back. I'll right-click the project and choose Manage NuGet Packages. On the Online, nuget.org tab, I'll search for knockout.typescript. This will find the definition file for the Knockout library as defined in the DefinitelyTyped project. Click Install and Close. Hmm, why didn't the type errors go away? I don't see the definition that we just downloaded in my TypeScript Virtual Projects window, so TypeScript must not be referencing it. By the way, if you don't see the TypeScript Virtual Projects window, you can enable it in the Visual Studio project options, go to Tools, Options, enter TypeScript in the search box, and navigate the Project General, make sure both boxes are checked on top, and click OK. It's a great tool for troubleshooting when Visual Studio's actually doing when compiling TypeScript code. One thing that's a bit annoying about the current version of the Visual Studio TypeScript plugin, as of Visual Studio 2013 Update 4, is that it doesn't immediately notice when you download a type definition from NuGet. In the TypeScript Virtual Projects node of Solutions Explorer, we can see that TypeScript is looking at lib.d.ts, app.ts, and gameclock.ts. What about the Knockout definition that we just downloaded? Well, you might remember this is a known bug. There are two ways to work around it. The first is to reference the definition manually. I'll go under Scripts, typings, knockout. If I drag knockout.d.ts onto the editing window at the top of this file, Visual Studio will explicitly reference this file in the TypeScript code. I could have typed out the reference comment too, but I like the drag and drop feature. Suddenly Visual Studio notices the definition and adds it to our virtual project, trouble is if I delete the manual reference, Visual Studio forgets about it again and our type errors come back. A better way to work around this that doesn't leave unnecessary references in our code is to unload the project via the right-click menu, and then reload it, or we can just use our VCmd macro. When you run the macro, make sure you click Yes to save the files that it tries to close, otherwise, you'll lose your work. Upon reload, Visual Studio will properly notice the definition file included in our project, and will reference it when compiling. You've only got to do this the first time you add a given definition from NuGet. According to Microsoft's TypeScript GitHub issues list, the team intends to fix this bug for version 1.5, which I'm guessing will come out in early 2015. Let's add gameclock.js to both of our HTML files and see if we're still functional. I'm adding the reference before coincounter.js to ensure that GameClock is available when Coin Counter gets initialized. (Working) When I run the tests, everything comes back green and the game seems to start up as expected. I think we're in good shape. Let's review our TypeScript conversion worksheet. Now that we've successfully converted GameClock to TypeScript, we've got to select the next part of our application to convert. Based on this chart and the guidelines we've reviewed in the past, I'd say the two best choices at this point are either to extract and migrate the coins array or else to migrate the tests for GameClock. In this logical diagram of the Coin Counter application, we can see that choosing the migrate coins would be a bit like starting over. While we want to migrate it eventually because it's used by CoinCounterViewModel, we won't be able to build upon any of the conversion work that we've already done. On the other hand, converting the GameClockTests allows us to validate our TypeScript GameClock implementation. The unit tests will not only continue to do their old job of validating the functionality, but they will also help us confirm that TypeScript is happy with all the ways we're calling in the GameClock. A good rule to follow is if code that you've just migrated to TypeScript has tests, the tests should probably be your next migration target. So coming up in our next clip, the migration of gameclocktests. Using Our Converted GameClock Back in Visual Studio, I'm going to rename gameclocktests.js to .ts, and I'll quickly reload the project to get compile and save working. Right away I can see that TypeScript is concerned about the QUnit global and QUnit standard parameters like assert. I'll fetch the QUnit definitions from DefinitelyTyped by opening NuGet and searching for qunit.typescript. (Working) And once again, I'll reload my project. You might be able to see why I recommended using the macro now. If we open up the error list and pin it, we can see that we've now got three distinct errors, five each of Only a void function can be called with the new keyword, and Supplied parameters do not match the signature of the call target, plus a lone implicit any violation. The supply parameters error basically means that TypeScript thinks that I'm calling something wrong. Hopefully, that's easy enough to fix. I'll double-click on the first one and Visual Studio brings me to some code that creates an instance of GameClock. I see one parameter getting passed in, that's the starting number of seconds on the timer, but not the other one that I set to callback. I have a sneaking suspicion that TypeScript thinks that the GameClock constructor arguments are both mandatory. Based on the tests, they're not supposed to be, so let's fix that. I'll right-click GameClock, and choose Go to Definition. Oh, sure enough we've not marked the arguments as optional. I'll do that by adding question marks to each of them. Now those errors have gone away, but they've been replaced by some pesky implicit any errors. I just want to remind everyone that in our project we voluntarily decided to disallow implicit any. If you're okay with not having TypeScript further check your code for correctness, you can simply allow implicit any in the project's TypeScript build properties and these errors will disappear. Another way to fix it would be to explicitly type all the instantiations of GameClock as any, though the syntax when doing that with new is a bit unfortunate. Var gc = new (any GameClock). Ugh, this is really ugly, plus the fact that now the tests just think that gc is of type any, so we don't get the full benefit of having converted GameClock to TypeScript. We get rid of that. What I'd like to do instead is provide TypeScript with an explicit signature for an instantiated GameClock, and then let TypeScript automatically flow those types into any uses of GameClock. This gives TypeScript the information it needs to tell me if I'm doing something wrong. There's two main ways of achieving this. The first is to keep GameClock essentially as is and annotate it with a TypeScript Interface. The second is to refactor the code to use the TypeScript class syntax. Either method is valid. Migrating to the class syntax means more changes to the existing code up front, though it's arguably more maintainable and semantic. By semantic I mean that it's clear to someone reading our code that we intend for GameClock to act like a class because we'll make it a class. Keeping with the original JavaScript style functional syntax means that we'll have to manually create and maintain separate interface code, but it's a bit faster to get started and there's less risk because we'll be making almost no changes to the existing code. We'll work with classes in a later module. Let's keep the GameClock code in the JavaScript functional style and get our strong typing by annotating it with an interface. At the top of the gameclock.ts file, I'm going to create an empty interface called GameClock, and I'll explicitly type the GameClock variable with the GameClock interface. You could call the interface something like iGameClock, but there's not any worry about collision in this case since we don't intend to use the name GameClock for anything else in our program. Now TypeScript is showing the error Cannot use new with an expression that lacks a construct signature. Okay, let's add one. I'll add a new function labeled new that takes the same arguments as the GameClock function does, and then type the result as GameClock. (Working) Wow, based on the count of errors you'd think we're doing worse here, but actually what TypeScript is giving us is a to do list. Each of the errors represents one of the members of GameClock that GameClockTests expected to see. Let's fill them in one by one. If we're sorting the error list by description, the first is addSeconds. When I double-click on that and click away from the errors pane, I can see that this is a method that expects a number. I can also go down to the bottom of the GameClock to see that. Let's add the method to our interface. I'll copy the call signature, scroll up to our interface, type in the name of the method, paste the signature, and then type it as void since it doesn't actually return anything. That fixed the error, but if I scroll down to the bottom of the GameClock and hover over addSeconds, I can see that it isn't strongly typed yet. Why not? An important thing to realize is that in normal TypeScript functions, meaning if you're not using lambdas, that this variable is explicitly of type any. This design choice means that you don't have to worry when adding members to this, but it does mean that you don't get strong typing from members hanging off of this, there's also no way to inform TypeScript what type this should be in a regular function, at least not as of TypeScript 1.4 that they're discussing it. Therefore, the best way to get strong typing with a regular function when using this is to capture it, and explicitly type the capture variable. In GameClock, I've already captured this using the variable self, which is a popular pattern when using Knockout, so I can now tell TypeScript that self is a GameClock. (Working) Wow, all this stuff we're missing on our interface internally also just lit up. Let's clear up the rest of these errors by adding them to our GameClock interface. Start is a pretty simple one; it's just the function that returns void, done. How about isRunning? I'm pretty sure that's a Knockout observable, but how should I figure out what the definition author called that type without digging around in the code? The easiest way is to let TypeScript tell you. I'll create a temporary variable called test. It's easiest if your temporary variable name's a few characters wide, and copy the declaration for isRunning to it. I can now hover my mouse pointer over test and TypeScript will tell me that this code produces a Knockout observable of type Boolean. The type part in the angled brackets is from the TypeScript generics feature. Let's delete test, and add isRunning to our interface. I'll also fill in secondsRemaining, which is a KnockoutObservable of number. (Typing) Let's unpin the error list now and do a split screen so we can keep editing the GameClock interface as we scroll down. Start is a function that returns void. Looks good. TimeRemainingFormatted uses the Knockout computed feature, so I'll use our previous technique to get TypeScript to tell us what type it is. (Working) Ha, it's simply KnockoutComputed to string. I'll get rid of test, add that to our interface, and then finish up by adding reset and stop as functions that return void. (Typing) Let's close the split screen, and open up the Error List again. Great, we're down to a single error now, which we'll get to in a moment. If I look at the members of GameClock that are attached to this by way of self, they're all explicitly typed, which is great. Even better, all of the test code that uses GameClock is explicitly typed, even though we haven't added any typed annotations in the test file at all. It's awesome when we're able to take advantage of type inference with TypeScript. If I make a mistake like a typo on a method name or calling a function with the wrong arguments, TypeScript will warn me immediately. So what about this remaining error? Well, occasionally TypeScript is a touch overzealous with regards to type checking and in my opinion, this is one of those occasions. TypeScript sees the GameClock as a function that returns void, and it isn't able to make the jump that actually GameClock is a JavaScript style constructor function. So, let's instruct TypeScript to not worry about it. I'll simply place an any type assertion at the start of the function and that should clear it up. Our internal method declarations will still be strongly-typed and our use of GameClock and the tests will also be strongly-typed. We're just asking TypeScript to trust us that GameClock implements this interface. I don't like using any since it's basically a junk drawer, you can't tell one variable of type any from another. In TypeScript 1.4, there's a new feature called name types that at least lets us keep our anys straight and apply some semantic meaning to them. I'll add the code type ClassFunction = any, and then assert the GameClock function as my new ClassFunction type. This has the same end result in the type system because we've said that the ClassFunction type is the same as any, but now at least I can strongly identify all places where I've done this particular workaround. If a future version of TypeScript smooths out this rough edge, I can easily right-click on ClassFunction, choose Find All References to locate them. Before moving on, I'm going to move ClassFunction into its own file since it's not actually part of the GameClock logic. I'll create a new TypeScript file called globals.ts, and place ClassFunction in there. This file doesn't get compiled into any useful code so I don't need to add it to the HTML files. (Working) Let's look at our conversion worksheet again, so far we've converted almost 30% of our originally code base to TypeScript when counted by lines of code. If we ignore the low complexity items for a moment, we've got three choices for what to convert next. Converting the tests for GameClock after converting GameClock itself worked really well for us last time, therefore, we'll put off converting gametests until after we've converted CoinCounterViewModel. Now it's between coins and CoinCounterViewModel. Hmm, 6 lines versus 270, and CoinCounterViewModel uses coins. I think we should do coins next. Wow, we've covered a lot of ground in this module. When we started, our Coin Counter application was all in one big JavaScript file, now we've extracted and converted about a third of it to TypeScript. We learned how to analyze a project for parts that make good early migration targets, and we discussed important process topics like source control and preparing your team. We were able to learn about TypeScript interfaces and type annotations. Along the way, we downloaded the library type definitions from NuGet, and successfully converted a class while preserving its JavaScript functional style. You're probably ready to take your first crack at TypeScript in your own project, but hang in there, we've got plenty more to cover including lambdas, and TypeScript classes, and internal modules. To kick off the next course module, we'll create our first TypeScript class using the class keyword as part of migrating coins. That's coming up next in Practical TypeScript Migration. TypeScript Migration Toolbox and Workflow Reimplementing Coins as a Class Welcome to module three in Practical TypeScript Migration. We've just finished migrating the GameClock feature and its tests. Now we're going to implement our first TypeScript class as we migrate the coins feature. Let's jump right in. I'm going to create a new TypeScript file in our project called coins.ts and copy the definition of coins there. (Working) I'll also clean up coincounter.js like I did before, in fact now, it's only CoinCounterViewModel plus that random global function down at the bottom. TypeScript is generally happy with coins as is, except that it's not sure what big is. I'll download the big.js definition from DefinitelyTyped and reload my project. (Working) Good, we don't have any compilation errors. Looking at this code, I think we might be repeating ourselves a bit. I wonder if it'd be better to just have a class or coin with a constructor. Let's give this a shot. I'll define a new class called coin and add a constructor function. I'll define the name, style, and value properties using the signature shorthand. Putting one of the keywords public, private, or protected in a constructor signature is shorthand for making the tagged argument into a simple property on the class. Hmm, it's not happy with Big, I wonder if I didn't specify the type correctly. How should I figure out the type? If you said let TypeScript tell you, you're paying attention. I can hover over value and TypeScript tells me that it's a BigJsLibrary.BigJS. That's a bit of a mouthful, but at least we don't have to type it that often. I'll correct the type in our constructor signature, and the error goes away. Moving on, I'm pretty sure we can safely derive the imgSrc property from the style. We'll always start the count at 0, so we don't need to pass either of those values to the constructor. Finally, we do need to know the max number of coins for a given type, so we'll add a regular parameter for that. We can wrap it in an observable inside the constructor itself. While we're at it, let's make max optional by providing a default value. Now that our constructor signature is done, let's add the remaining coin properties. ImgSrc is a string, public imgSrc: string, and both max and count are KnockoutObservables of number. (Working) Now, let's set the values of these items in the constructor. I'll base the value of imgSrc off the value of style. Then I'll hardcode count to 0 and set the max property to the value passed into the constructor. (Working) We previously discussed that TypeScript can't always know what type this refers to, but inside our constructor function, TypeScript knows that this refers to the class. On the final line of our constructor, this.max refers to the class property and max refers to the constructor parameter. Finally, let's redo our coins array to use our new class. I'll make a copy of coins and rewrite it quickly. (Working) Good thing I took those typing lessons. Let's add coins.js to our HTML files and see if they work as expected. (Working) Ouch, not quite. What happened here? I'll click Yes to debug. The error message is Object doesn't support this action. Well I'm so glad they made that clear. Let's see if the debugger can help me at all. I'll hover my mouse pointer over coins, it's still undefined, but that makes sense because the value of the array literal hasn't been assigned to it yet. Oh, it looks like coin is also undefined. I imagine that coin should already a value if we're going to be calling into it. I wonder why it doesn't. Let's look at the generated JavaScript to investigate. I'll click the Switcheroo button in the IE debugger button bar, that'll swap out the source map TypeScript file and show the JavaScript that's actually being executed. It looks like we're trying to set up coins before the line where we set up coin, but aren't vars supposed to be hoisted in JavaScript? Yes, they are, but the act of assigning a value to them is not, so it seems what's happened is that the declaration of coins has been hoisted to the top and the declaration of coin has been hoisted to the top, but a hoisted variable's value is undefined until the line of code that assigns it a value has been reached. Coin doesn't get a value until line 7, but we're trying to call onto coin on lines 2 through 5. The calls to new up a coin failed because you can't call new on a still undefined variable. We simply haven't gotten to where coin gets defined yet. Going back to our error, I guess it makes sense now, an undefined variable doesn't support the action of calling new on it. What's the fix? Have the right ordering. I'll close the browser and move the assignment to coins below the declaration of the coin class. Let's see if everything works now. (Working) Great, the game starts up as expected and all the tests pass. Once again, we'll go back to our conversion worksheet. This time we can mark coins as completed. Well, other than the two trivial things, there's not much left to migrate, but CoinCounterViewModel or the tests for it. As we know, it's often best to migrate the tests for the thing after we migrate the thing itself, so let's get started with CoinCounterViewModel. We'll use everything we've learned so far and more to tame this beast. Are you ready to get started? Let's go. Migrating CoinCounterViewModel as a Function I've got coincounter.js open in Visual Studio. I could create a new TypeScript file like we've been doing, but since CoinCounterViewModel is basically the only thing left in this file, I'll just rename it entirely to CoinCounterViewModel.ts. Then I'll reload my project to get Visual Studio to recognize the new TypeScript file. Twenty-seven errors. Right off the bat, TypeScript is telling me that it can't find name $, that's jQuery. I'll add the definition via NuGet by searching for jQuery.typescript, Install, and Close. And once again, I'll reload the project, remember, you've got to do it every time you pull down a definition from NuGet. Okay, 18 errors now. Let's keep going. Let's work through these implicit any errors from top to bottom. I'll double-click on the parameter callback here and let's fix up these parameters. Message is likely to be a string. Timeout is getting past the setTimeout function, so I expect that that's a number of milliseconds, and I can see by the way that callback is used, that it's a function that returns void. Callback seems to expect the current instance of CoinCounterViewModel to be passed to it. I can type that as viewModel typeof self returns void. Why would I use typeof self? Well as of right now, self is explicitly any because it's been assigned from this at the top of our function, however, if we ever change that self will be some other type, and that will flow through to this callback argument's type without us having to revisit it. We're down to 15 errors. Coin implicitly has an any type. I'll update each of these to reference our coin class. By the way, before I update addCoin, notice how TypeScript doesn't know the type of oldCoinCount, but when I annotate the coin parameter as an instance of the coin class, now that type flows through and oldCoinCount is strongly typed. I'll fix the rest of the coin errors quickly. (Working) We're down to 12 errors now. I'm going to leave addCoinEnabled and removeCoinEnabled for a bit later because I want to take some time to discuss what that code is doing. I'll double-click the next implicit any error for coinName. CoinName seems to be a string and zeroBasedIndex a number. Double-clicking the next error, inputString is clearly a string. Hey, you just updated our miscellaneous global item by accident. I'm not sure this really belongs in the CoinCounterViewModel file, so let's copy it over to the globals.ts file. Continuing on, theScore seems to be some sort of object that has a score and name. Let's use the split screen view again and work on an Interface. (Working) When I create the interface HighScoreItem and assign it to the parameter theScore, inside the function, score and name light up as errors. I'll fix those by adding them to the interface. While I'm looking at it, I'm also going to clean up this error at the top of the file. Basically we're declaring CoinCounterViewModel, and then assigning CoinCounterViewModel a value in the very next line. Why don't we consolidate that by just getting rid of it, that way CoinCounterViewModel will also be implicitly typed because we're assigning it a value at its declaration. Next is this addCoinEnabled thing. Oh, I remember this code. Remember how each coin looked like it was just a simple object literal? Well, that wasn't actually true. When instantiated, the CoinCounterViewModel was actually looping through the coins array and adding Knockout computeds to each coin, these computeds serve as UI helpers. One thing about TypeScript is that it really doesn't like you to add stuff to an object that it doesn't expect. Since our coin class definition doesn't include an addCoinEnabled or removeCoinEnabled member, these calls fail, we can fix this by adding member stubs to the coin class. AddCoinEnabled is a KnockoutComputed with Boolean, and so is removeCoinEnabled. (Working) Honestly, I'm not sure if it makes sense anymore for the CoinCounterViewModel to be adding these members. I guess it's because part of the calculation involves the buttonsEnabled function on the view model and the coins don't have any reference back to the view model itself. Let's consider that for a future refactoring as well. We're down to just five errors now. Property modal does not exist on type jQuery. Hmm, modal here refers to a Bootstrap modal. Let's grab the type definition via NuGet. I'll search for Bootstrap.typescript, and install it. (Working) When I reload my project, the modal errors go away and I'm down to just two. The next error is string is not assignable to type Location. Oh, well that's funny, I guess I was just using this wrong. I should have assigned the new URL to window.location.href. That's one of the funny things about using TypeScript, you start wondering how your code worked at all before. Lastly, message has an implicit any type, it should be a string. Great, all of our type errors are gone. Let's update our HTML files to reference the new emitted JavaScript files, both globals.js and CoinCounterViewModel.js, and launch the application. Okay, update index, and Ctrl+F5, check the test first. Okay, green, let's see if we can play. That's a hard one. Fifteen cents, good. And we'll just goof this one up on purpose. Well our tests run and the game seems playable, great! We knocked out the CoinCounterViewModel and that miscellaneous global. The only code of any importance left is the gametests, let's do those now. Converting CoinCounterViewModel to a Class Back in Visual Studio, I'll rename gametests.js to gametests.ts, and reload the project. Oh good, only three errors. Oh, new expression whose target lacks a construct signature implicitly has an any type. TypeScript is essentially telling me that CoinCounterViewModel isn't a class, even though I'm calling new on it. It's the same problem we had when we converted the gameclocktests, rather than use the light touch interface technique that we used for GameClock, keeping with the JavaScript functional style, let's go all in and actually convert CoinCounterViewModel to a TypeScript class. I'll replace the top line with class CoinCounterViewModel {. Ouch, that's a lot of refactoring to do. The error window says 101 errors, but really that just means that Visual Studio counted to 100 and then gave up. Visual Studio 2015 will at least be able to show more than that. So how about some tips to handle this level of refactoring efficiently? First, use strict isn't supported as a statement inside the TypeScript class as a 1.4, but you can use it at the file level, or in functions, or modules. My recommendation is to place a use strict in a module that contains your classes. I'll demonstrate that later, so for now, we can just get rid of the use strict here since the code in this application doesn't strictly, ha ha, depend on it. Next, I'll make some room and then type collapse into the quick help box. That'll remind me of the keyboard shortcut for collapse of definitions, Ctrl+M, Ctrl+O. Okay, at least I can get a sense of the scope of this thing now. A lot of this work is just going to be replacing self with public. Once you switch to the idiomaticTypeScript class syntax, it becomes unnecessary to capture this as a separate variable. In fact if you do it, TypeScript will want you to type this.self to get to it. What we need to do is remove the capture of this, and then change any uses of self to just say this. These calls are a bit different though, in TypeScript you can't just add stuff to a class, you have to declare it with a visibility modifier. As such, what we need to do is change each of these self calls to say public. We can worry about making some of them private later if we want to. Since I've collapsed the definitions, it will be useful to do a multiline select in Visual Studio by positioning the cursor to the left of the first self, holding down Shift and Alt, and then using my down and right arrow keys to navigate to the bottom self and across covering the periods, and I'll simply type public space. How about that? We're down to 58 errors now, plus we get to look awesome in front of our coworkers. I'll press Ctrl+M, Ctrl+L to expand all definitions. Let's get rid of all the self calls and replace them with this. I'll open the quick replace, select current document, search for self., and replace with this.. I'll go through this manually and look for anything unusual as this string based searching is not a safe refactoring. (Working) Cool, actually everything looked okay. Next, I'll also search for self without the dot, and replace it with this. Var self = this. It's no longer necessary to capture this inside a proper class, we're just going to use the keyword this directly, so I'll get rid of this statement. Next, we'll look over at the callback argument. Previously, we were able to take advantage of the typeof operator since we were using the variable self that was implicitly typed as whatever our view model was, now since we actually have a name for the type because the type is a class, let's just use that instead, CoinCounterViewModel. Now, we've got an error Argument of type Window is not assignable to parameter of type CoinCounterViewModel. One of the funny things about using self as a standard capture variable name is that if you take it away or forget to declare it, self points to a default property of the window object. Basically, a global called self, and that's what TypeScript thinks we're trying to use here. Clearly I wasn't careful enough before when I was doing my find and replace refactoring, and honestly, that's a problem you run into when you're kind of in between JavaScript and TypeScript. Now that we're free of TypeScript errors, let's run the app and see how it goes. Whoops, okay, it seems that the language service got a bit out of sync from the build. The TypeScript service in Visual Studio has gotten pretty reliable since 1.3, but this still does happen occasionally. I'll hit No and yep, okay, we've got a few more errors to handle. By the way, you can tell that these errors came from the build because they're labeled Build. Such errors won't go away until you try to build again, as opposed to the errors generated by the language service that'll appear or disappear as you type. Well, actually this is a strange one, I set up QUnit in such a way where if the library was properly referenced, then nothing would happen, but if it were not properly referenced, the value of QUnit would explicitly be null, and the if block on line 2 wouldn't try to run. It was basically a way to gracefully fail on the tests if QUnit couldn't be loaded. This is confusing to TypeScript now because we're doing this in both test files. The error itself is actually somewhat helpful if read carefully despite the typo, QUnit is implicitly any because it does not have a type annotation, so let's annotate it in both files. (Working) I'll hit Ctrl+Shift+B, and now our build succeeds. Now that we're free of errors again, let's try to run the app and see how it goes. Ouch, Unable to get property isRunning of undefined or null reference. Let's open the debugger. Hmm, the error happened inside a computed. What's happening is that this is referring to the window and not the class. The way to have TypeScript automatically capture this for us inside a function is to rewrite as a lambda. Wait a minute, hold on Steve. Now you're really confusing me. First you say we have to capture this, then you say we don't need to capture this, and if we've captured it, we need to replace our capture variable with this. Now you're saying we need to rewrite functions as lambdas because this isn't getting captured? What are you rambling on about? What the heck is a lambda anyway? Okay, let's take a step back, and talk about everyone's favorite JavaScript subject, this. Lambdas and How 'this' Works in TypeScript Let me start by saying that the way that this works in JavaScript is often confusing, it's even confusing to talk about this. You end up having to over enunciate to make it clear when you're talking about the keyword versus just using the word this, but confusing this is not just a TypeScript thing, it's a JavaScript thing too. In JavaScript, the this keyword is contextually bound, this means that the value of this depends on how you call the code that contains it, rather than what code contains it. Sometimes this behavior is awesome, such as in functions that handle DOM events. It's nice that browsers bind this to the control that fired the event. In other scenarios, the binding of this can be difficult to predict. Now, let's talk about what a lambda is. You should already be familiar with JavaScript standard function syntax. We have the keyword function, and a named argument list, and a body surrounded by curly braces that may or may not have a return statement. TypeScript lambdas are a shortening of that syntax based on the coming ECMAScript 6 proposal, the function keyword is eliminated and replaced by a fat arrow after the parameter list that indicates the body of the function. It's a terser syntax that many developers prefer, in fact when using lambdas, one-liner functions that just return of value can omit both the return keyword and the curly braces. For an even more minimalist lambda, a developer can even omit the parenthesis around the argument list, though that only works if there's a single parameter and TypeScript doesn't allow specifying the type, so the super minimalist style doesn't work if you disallowed implicit any like we have in Coin Counter, notice our red squiggle, but if you're allowing implicit any, this last form works perfectly well. When you're using standard function calls, this in TypeScript works identically to how this works in JavaScript. When you use a lambda, TypeScript automatically emits some extra JavaScript to capture this from the scope where the lambda is declared, then any time you call this from within the lambda, the automatically captured this gets used instead of the this that would otherwise be there. When writing code in a classical style, meaning code-oriented around calling methods on classes, this is usually what you want. So you might be thinking, how do I use the nice lambda syntax if I don't want to use a lexically bound this? The answer is, you don't. If you want your this to be contextually bound, meaning the way it works in normal JavaScript, you have to use the function keyword. If you want your this to be lexically bound, use a lambda. So it's important to realize that the lambda isn't just syntactic sugar, it really does have a different functionality in that regard. I found that when I'm using TypeScript classes, I can keep this straight fairly easily by always using lambdas, except in the few cases where I really do want this to be contextually bound. When I'm writing code in a functional style, I often prefer to capture this myself, that's why I was using self throughout our code base, then I can pick and choose if I really mean to use whatever this is contextually bound to, or whatever this referenced when I captured it. To review before we get back to migrating our code base, how this works in TypeScript is often confusing. I put a link here to a document on the Mozilla Developer Network that I think explains this fairly well, and of course check out the many other excellent JavaScript courses available on Pluralsight. When using lambdas in TypeScript, this is lexically bound, meaning it's automatically captured for you. The emitted JavaScript uses the _this variable for that purpose, though it's a compiler error, it's a reference underscore this directly in your code. I've searched for the word computed in this file using find all. I'm going to rewrite isPaused so that it uses a lambda instead of a normal function. Doing so will ensure that this still refers to the class when the computed is calculated. I'll repeat this process for any functions that reference this where this is intended to point to the current instance of the class. In all, there will only be a handful of regular JavaScript functions remaining. I'll be honest, this part of the conversion from JavaScript to TypeScript is tedious and error prone. Since there's a lot to do, I'm going to do the rest of the work mostly off camera. I think I'm done, but I haven't saved the file yet. I want to show you what the emitted JavaScript looks like when I'm using lambdas. I'll pull across the Web Essentials window. As I save, notice that the emitted JavaScript shows that TypeScript captured this as _this. Anywhere I've referenced this inside a lambda, TypeScript will emit _this instead. Let's try it again. Object doesn't support property or method buttonsEnabled. Well, it's a different error at least. Let's open the debugger again. Oh, this is that oddball function again where I'm adding functions to the coin class from the view model. We'll turn off source maps to see what's actually executing. What's happened is that this has been captured a second time because I'm running that code inside an immediately invoked function expression. We'll need to do more refactoring of lambdas. In fact, what I'll do now is run through the class and wherever this is used at all, I'll just change the function to a lambda. I'll press Ctrl+F, type this, set the scope to Current Document, and choose Find All. Let's see how quickly I can refactor this. Remember, I'm looking for functions that reference this when this is intended to point to the current instance of the class. (Working) While I'm refactoring, I need to keep an eye out for functions that pass a callback, checkforVictory has two of them. The callbacks also need to be lambdas if we want this to reference a class instance when the callback is executed. (Working) Here's that initialize function with the call to buttonsEnabled that threw an error in our last run. I didn't realize it initially, but there's actually several levels of functions here that I need to convert as lambdas. Since I didn't convert all of them before, this was recaptured by TypeScript in the emitted code, which meant that it didn't refer to the class anymore as intended, that's why we got that error. Let's test out the application. Eighty-five cents, quarter, quarter, quarter, dime, correct! And we'll goof this one up on purpose. Incorrect! I'll let the timer run down. Cool, game seems like it's working. Good news is that now we're error free, and by the way, in gametests, if I go to line 25 and I hover over CoinCounterViewModel, you could see that TypeScript thinks that it's a proper class now. I can run the application and it seems to work, and when I run the unit tests everything comes back green. I think we've successfully converted Coin Counter to TypeScript. Completing the Migration and Internal Modules We've done quite a bit of work on our Coin Counter game and have very nearly completed our TypeScript migration. You've seen a great deal of what's required to move a code base from JavaScript to TypeScript, and I'm sure that you've gotten the sense that it can sometimes involve significant work to get right back to where you started. What you haven't seen much of is how comfortable it is to do normal development work in TypeScript, so I say, why don't we get this last little bit of code migrated over to TypeScript and then let's do some stuff for us. I think we can make three significant improvements to this code base now that our TypeScript migration is complete. First, I'd like to get our code out of the JavaScript global namespace. Right now, we've got lots of code hanging off the window object in the browser. We can take advantage of TypeScript internal modules to reduce our code's footprint in the global namespace to a single variable called CoinCounter. Next, I mentioned in a previous module about how coin and the CoinCounterViewModel classes have an awkward relationship. As it's currently programmed, each coin object winds up being in charge of whether its corresponding buttons on the UI are enabled. It'd be better if each coin were only in charge of coin stuff and the view model was in charge of the UI buttons, so we'll do some work to fix that. Lastly, I mentioned earlier that CoinCounterViewModel is in charge of basically everything in our program, that's not really a great way to design your code if you want it to be maintainable, so we'll take a first crack at refactoring CoinCounterViewModel by extracting the highScoreList code into its own class. This isn't a complete refactoring, but just the first step. Every TypeScript error that comes up while we're refactoring is potentially one browser refresh cycle saved. I hope you get a sense of how pleasant doing actual work in TypeScript can be. First, let's get this final bit of inline JavaScript in our HTML file migrated over to TypeScript. I'll open up index.html, and navigate down to where it's listed, cut it out, reference it to index.js, and create an index.ts file. I'll paste that code in. Party time! We're a 100% TypeScript. Next, we said we'd do some work to get our code out of the global namespace. I think CoinCounter is a good module name to use. Let's wrap our app code in module CoinCounter, open curly brace, close curly brace. Look what happened down in the Error List, TypeScript is telling us exactly where we've broken our code by putting app in a module, but don't worry, most of these errors will go away once we finish putting everything else in the same module, so we won't take action on any of these errors just yet. Let's take a look at what TypeScript emitted. It's declared a variable called CoinCounter and then run an iffy passing that CoinCounter variable inside. It's not actually doing any work on CoinCounter just yet though. For that we need to add the export keyword to app. Once we do that, the app variable will be set as a property on CoinCounter in the emitted JavaScript and will be usable anywhere that CoinCounter is usable. If you don't export a member in a module, then it's only usable by things inside the same module within the same TypeScript file. Let's wrap the coin class in the CoinCounter module also. Then we'll have to export coin and coins. By the way, while we're here, I noticed that in an earlier module I forgot to set the maximum number of quarters as 4. I fixed that off camera. The next class to wrap is GameClock. Technically in TypeScript 1.4, you don't have to export the interface that something implements, but I'm not entirely sure if that's intended or a bug, so I'll export our GameClock interface. I'll also export the GameClock constructor function. On globals.ts, I'll wrap everything in the module and export both the type and the function, and I'll also wrap the code in CoinCounterViewModel exporting just the CoinCounterViewModel since the HighScoreItem isn't currently used in any other code files. Now, everything that we want to put inside the CoinCounter module should be in there so we can start dealing with the Error List. The fix for all of these errors is simply adding the CoinCounter. in front of the calls that used to be global. I'll quickly run through and do that. (Working) Let's try out our app. Ouch, I thought TypeScript was supposed to help us avoid errors. Okay, let's open up the debugger. The error is spacesToUnderscore is undefined, that was a random global function that we moved into globals.ts, now it's in a namespace so when Knockout looks for it on the global scope, we can't find it. Wait, why is Knockout calling a global function instead of just using whatever our view model provides to it. I'll bet there's something ugly lurking on our HTML. I'll close the browser, open up index.html, and search for spacesToUnderscore. (Working) Sure enough, we're doing logic in our view, which is a big no no. It's best to keep your views as dumb as possible and do logical work in real code. This is a great example of how TypeScript isn't magical, it can't help you with code that isn't in TypeScript or is at least isn't described in TypeScript. I'm fairly certain there is a function that already does this in CoinCounterViewModel. I'll flip over there and search for spacesToUnderscore. Yep, there it is, it's called destinationDivIDForCoin, and it requires a coin object be passed in. Let's copy the method name and modify our HTML. I can reference this method by calling $parent first. We're inside a for each loop over coins and the parent in this case is CoinCounterViewModel. Then since the method requires a coin be passed in, I'll specify $data, which in Knockout is our current object in the for each. Let's check it out. I'll enter my name, quarter, dime, dime, penny. I can make 46 cents with no issues, and when I run the tests, they come back green. Awesome, that was a fairly major refactoring for code cleanliness and it just took us a few minutes, not bad. TypeScript Internal Modules vs. External Modules While we're on the subject of TypeScript modules, I'd like to offer some commentary. We just implemented what TypeScript calls internal modules. As we've seen, when we use internal modules, you can fairly easily reduce your code's footprint in the global scope to just one variable. In our case, the variable name was CoinCounter. Internal modules are also open, this is why we can declare the CoinCounter internal module in multiple files and we didn't have a name collision. In fact, the items we exported from each became part of one shared CoinCounter variable. Internal modules don't require any special libraries to get working, you just reference the emitted JavaScript files and the module names show up in the global scope. If the term internal module sounds confusing, you're in good company. As of March 2015, there's a discussion thread on GitHub where the TypeScript Team has suggested adding the namespace keyword to the language. This would be used instead of the module keyword when implementing internal modules. I think that makes a lot of sense because generally that's how internal modules are used and practiced as a way to create a namespace for your code to live in. In addition, internal modules, or what might soon be called namespaces, TypeScript supports something called external modules, I like to think of them as physical modules or file-based modules. When we reviewed the Visual Studio TypeScript build properties window, we saw the two flavors of external modules supported by TypeScript, CommonJS and AMD. CommonJS is the module system intended for use with Node, though CommonJS modules can also be used in the browser if processed by tools like Browserify or webpack. AMD is the module style designed for use in the browser quite often with the library RequireJS. To get TypeScript to compile a file as an external module, just add the export keyword to a variable, module, or class, or put an export = statement at the bottom of the file. Now, I hate to bring this up because it's a bit controversial and external modules are technically outside the scope of this course, but I feel like it's important to share a quick editorial on using TypeScript modules when coding for the browser, since I see a lot of questions about this on Stack Overflow and GitHub. Developers getting started with TypeScript ask the question, what style of modules should I choose, internal modules, perhaps soon to be called namespaces, or external modules? My answer is: choose the module style that keeps the complexity of your project to a minimum. Internal modules are so simple to get started with as we've just seen. In my experience, they just work in projects from the most trivial all the way up to medium complexity, however, internal modules do start to suffer from some problems in high complexity projects with many library interdependencies. We've even run into one of those in CoinCounter, the need for a developer to manually maintain the script load order. It's not so bad with 11 runtime scripts like we have, but imagine if it were dozens, or 100, or even more. It's not hard to imagine a developer spending more time managing changes to script interdependencies than coding the new feature that required them. External modules can help automate interdependency resolution, but they introduce problems of their own, especially when using TypeScript. There's a fair number of concepts that you need to master across several disciplines to be effective with external modules. These things simply aren't a consideration with TypeScript internal modules. In trivial or simple projects, this means extra headaches with no real benefit. To help you select a module style appropriate for your project, I drew up a little chart. The y axis is called Level of Effort, but I almost called it hassle factor. The x axis describes what type of project you're working on. To be clear, this chart refers only to client side complexity in the browser. CoinCounter is decidedly in the simple range. It wasn't a lot of effort to implement internal modules for CoinCounter once we finished our TypeScript migration, but we did most of the work on CoinCounter without them. I'd say we didn't really miss them much, but with internal modules, CoinCounter's code base is ready for further growth, so we did get some benefit. I could have chosen the refactored CoinCounter to use external modules, this would mean having to select a module loader and to learn the ins and outs of using it with TypeScript. That represents a medium amount of effort, certainly more effort than tagging the word module on all of our code files, and when we were done with that effort, I'm not sure we'd find ourselves in a better place than we are having implemented TypeScript internal modules. With internal modules, we get the benefit of more structured code, while keeping our concept count down. In medium projects, the story starts to change a bit. This might be a project with two or three dozen scripts and a small team of developers. Having no module system at this level means that managing your scripts and their interdependencies becomes quite difficult and I really can't recommend it. Internal modules, however, work quite well. The developers might spend a bit more time managing scripts than they do in simple projects, it's not yet too burdensome. At this level, if your team is happy with internal modules, definitely stick with them, but if you observe your project getting more complex, it would be entirely reasonable to research external modules. In high complexity projects, internal modules start to be problematic. This type of project often involves a handful of teams working on many dozens of scripts and libraries. There's a lot going on so it becomes difficult to manage script interdependencies manually. This is when implementing external modules starts to actually decrease the level of complexity of your project. Developers on projects like this have already found themselves in a complex situation, therefore, the extra effort required to implement TypeScript external modules may offset the effort the developers would expend to maintain the inner relationships of the TypeScript internal modules. It's not a bad thing to use internal modules in a system of this complexity, but this is about the limit of their effectiveness. In projects that are extremely complex with multiple teams and hundreds of scripts, it can be quite difficult to maintain internal modules, so external modules are likely a better choice. From time to time, I see people getting told that they should always use external modules. External modules can help you in projects of extreme complexity so they must always be better, right? I disagree with that. There's a lot of simplicity that you trade away for the functionality of external modules. Internal modules are awesome in projects of medium complexity or less, past that, you'll have to evaluate the pros and cons yourself, but don't feel pressure to take on the burden of using external modules if their benefits won't actually help you, compared it with internal modules. I hope this chart helps you make the right decision for your project. I should probably say that if you're converting a JavaScript project that already uses external modules and you're happy with them, stick with the system you've got. Now, over the next few years, there's going to be a lot of discussion happening on this topic due to modules becoming part of the official ECMAScript specification. The TypeScript Team will support ES6 modules as of TypeScript 1.5. Since ES6 modules are similar to today's TypeScript external modules, we'll have to see if this changes the recommendations. Stay tuned for that. Back to our refactoring. Separating Coin and ViewModel Concerns Okay, the next item is cleaning up the UI logic that's bled into our coin class. I'm going to open up CoinCounterViewModel, and scroll to that initialize method that adds members to each coin at runtime. A coin really shouldn't care if a UI button is enabled, but I do think that each coin object should know if it can have additional coins of its own type added or removed. Let's just get rid of this whole block of code. I want to add some new methods to coin and I'd like to write some unit tests to help me. Since we don't have a cointests file yet, I'll make a copy of gametests and rename it cointests.ts, then I'll clear out pretty much everything except the default test and rename the QUnit testing module as cointests. I'm going to write a test called Can't remove when zero. Inside the test I'll create a new test coin with some junk data, then I'll ensure the current count of my coin object is set to 0. After that I'll assert that a new property on that object called canTakeAway is strictly equal to false. StrictEqual is just QUnit's way of letting you say that you want to assert a quality using the triple equals. This is a super informal flavor of the red-green-refactor test-driven development practice. We've got a failing unit test here, failing to compile is considered a failure, that's our red. Now let's turn it green by implementing the code necessary for it to at least compile. I'll declare canTakeAway as a KnockoutComputed of Boolean, and then implement it in the constructor. This.canTakeAway, Knockout computed, I'll use a lambda here, and we'll just return if the count is greater than 0. Now that my errors are gone, I'll duplicate the previous tests, except this time I'll ensure that a coin can't be added if the coin is already at its max. (Working) Once again, I'll declare and implement the member. (Working) I'll add cointests to my tests.html file and try to run them. Now I haven't modified the view or view model yet, so of course there's an error, but I'm just interested to see if my new unit tests work. I'll run them and good, they came back green. I can pop them both open too, you can see the details of the assertion. Now, let's update the CoinCounterViewModel. I'll add two methods called addCoinEnabled and removeCoinEnabled with the same logic as we had previously, except the functions will accept a coin object as a parameter. This first one will reference canAddMore and removeCoinEnabled will reference canTakeAway. Then I'll search for removeCoin in the index.html file and update the binding. Each coin's remove button will be bound to $parent, which is the view model .removeCoinEnabled passing in $data, which is a coin. Then I'll bind each add button to $parent.addCoinEnabled passing in the coin. Let's try it out. I can add up to 10 pennies and can't subtract once I reach 0. I can also add up to 4 quarters and I'm similarly prevented from going below 0. If I run the tests, everything's still green. Well that seemingly worked pretty well. We saw how TypeScript helped us get the red in our red-green-refactor loop without actually having to run the code, but it may have also been clear again that TypeScript wasn't able to help us with our binding expressions, so keeping the least amount of logic in them as possible can help greatly. Extracting a Class from CoinCounterViewModel Okay, in this last part, I'd like to do some refactoring on CoinCounterViewModel. There's plenty that can be done, but I've decided that first I'd like to separate out the high score logic to its own file to improve our separation of concerns. The first part of the high score logic isn't even in CoinCounterViewModel, it's in app. I'll create a new TypeScript file called HighScore.ts, then I'll define a section to be included in the CoinCounter module and export a HighScoreList class. I'll grab the starterHighScoreList from the app variable, and place it inside our new class. I'll fix up some of the indenting, mark it public, and then specify that it is a HighScoreItem array. Hmm, I guess that HighScoreItem interface from CoinCounterViewModel belongs in here too. I'll copy it over. Now that we're declaring this interface here, but using over in the CoinCounterViewModel, I'll also have to export it. Let's grab HighScoreList from the view model and paste it in. We'll just comment it out for now. (Working) I'll change the reference to app to say this since the starter list is here now. Hmm, our starterHighScoreList can probably be private since we'll only be calling it from within this class. Okay, next I'm going to copy the tryPushHighScore method and paste it into highScoreList. Now that I've brought it over, I think we can simplify the list member to be just list. I'll right-click, Refactor, Rename, type List, hit OK. You can see that TypeScript made the appropriate changes. Now let's clean up these errors. I'll double-click one of them. TypeScript is telling us that tryPushHighScore doesn't exist on CoinCounterViewModel, of course we just moved it over to highScoreList. Let's fix that by moving this line up to the top so it'll be processed early, and change the call to new up a HighScoreList. Now we can fix line 7 to reference our new instance. Our remaining error is in the gametests file. Now that we've change the highScoreList from an observable array into a class that contains an observable array, we don't need to put the parenthesis here. However, now TypeScript tells us that the class doesn't have a length property. This kind of instant feedback is helpful because I might have just spent 30 seconds trying to run this, instead of knowing immediately that it's not going to work. I'll change the call to hsl.List.length. Here's something important though, TypeScript does its best given the information available to it. A KnockoutObservableArray has a length property, but it's not the one we want. We want the one that comes from calling into the observable that returns how many elements there are. So this is just a reminder, that while TypeScript does its best, occasionally APIs have places where it's easy to make a mistake and TypeScript can't help you because the code you wrote is technically valid. Another thing we'll need to do is get rid of this comparison of the constructor. The assertion is no longer valid since hsl is an instance of our class. On our next line, we'll create a new assertion that instead will use the instanceof operator. (Working) Let's add our highScoreList JavaScript file to HTML files. (Working) Oh, and in index.html, let's make sure we're binding to the list object on line 110. We'll launch the app and try it out. I can click the High Scores list and Alice, Bob, and Charlie are listed. When I resume the game, I can make any 81 cents without any trouble. I'll make 92 cents to run up my score to 20 points, and then I'll let the game clock expire. When I open up High Scores list, I'm now in second place, not bad. Here's a quick point I forgot to mention earlier, now that we've got our code wrapped in TypeScript internal modules, we can take advantage of ES5's strict mode by placing the string use strict just under each module declaration. Off camera, I've added use strict to all the CoinCounter module declarations in our TypeScript files, so you'll be able to see them in the after code samples for this module. When you put use strict on a TypeScript module, its effect is active for all members contained in that declaration only. This means that if you want strict mode to be on in all of your TypeScript files, you have to add it at the top of each module declaration. An interesting side effect of the way that TypeScript internal modules work is that if you have some code that breaks in ES5 strict mode and you don't have the time to rewrite it yet, you can isolate it in its own module declaration and leave use strict off. The example code at the top is included in my module, but does not operate in strict mode, that's why I can call delete on a variable without my script erroring out. The code at the bottom does operate in strict mode. The nice thing is that a consumer of my module could call both functions and wouldn't need to know the difference. In this clip we were able to make quite a number of improvements to Coin Counter's code and TypeScript helped us be more productive. With TypeScript internal modules, we got our code out of the global namespace, except for one variable. We improved the confusion of concerns with coin by doing some refactoring and we took a first step towards simplifying CoinCounterViewModel by extracting the HighScoreList class from it. We've done a ton with Coin Counter and you've seen how good the developer experience is with TypeScript once you've got everything converted over, though TypeScript isn't omniscient. In the next module we'll see how we can take advantage of some free tools to improve our website's performance, and make our TypeScript development experience even better. TypeScript Build and Test Pipeline Building TypeScript with Grunt and Node.js Welcome back to Practical TypeScript Migration. In this module, we're going to check out a few tools that are useful for developers working with TypeScript. All the tools we'll see here are written in JavaScript or TypeScript and run with Node.js. Up until now, we've only been running JavaScript in the browser on a web page. Node.js and forked projects like io.js provide a container where JavaScript can execute from the command-line, and take action just like any other program. The team that developed Node took the V8 JavaScript engine that powers Chrome, and wrapped it up in an executable, and provided a set of APIs that work on Mac, Linux, and Windows. I have to be honest, I was rather skeptical when I first heard about Node, and since my day job is as an ASP.NET and SQL Server developer, I haven't personally used if for hosting actual production websites, but in the past year or two, I've found that libraries written for Node are great for web development tooling. My goal with this module isn't to give in to you that Node is the greatest thing ever, I just want to show you some of the stuff that's possible, how easy it is to get started, and get you to say something like, huh. For me, getting started with TypeScript was a slippery slope to getting involved with Node. So, what are you going to get out of this? By the end of this module, we'll have created a build script for our site using Grunt. The script will build our TypeScript, bundle and minify the resulting JavaScript, and run our unit tests. The cool thing is that any other developer on our team will be able to repeat this process on their machine, even if they have a Mac or on Linux, as long as they have Node.js or io.js installed. They'll have to pull down some files from source control and run a simple set of commands or two, which we'll document, but after that, anyone can repeat our build process by running just one command, that's really powerful for a team. To get started, I'm going to download and install Node.js. You can get it from nodejs.org and the Install link is right on the home page. When you do install Node, you actually get two things. The first is the Node.js execution environment, the other thing is npm. Some people say that NPM stands Node Package Modules, but every time I load the npmjs.org website, they'll give you a new definition in the upper left hand corner. The last time I went, it stood for No Problematic Moustaches. Npm is a program that lets you interact with the npmjs.org package registry. For .NET developers, you can think of npm as the JavaScript version of NuGet, though there are certainly some differences. We'll use npm to pull down some packages to work with Coin Counter. Npm modules tend to assume that you have Git available in your path. This doesn't mean you have to use Git as your source control system, just that npm will be able to call Git to pull down packages. If you don't already have Git installed, you'll need to do that. MsysGit is a popular Windows Git client, but I usually use portable Git, which comes with GitHub for Windows. Either way, as long as Git is in your path, you should be able to use npm without any issues, so of course neither of the tools I just mentioned will put Git in your path by default. If you install msysGit, you have to change this radio box in the installer to automatically put Git in your path. The third option isn't necessary unless you really want those UNIX tools. If you choose to use GitHub for Windows, you can edit your nodevars.bat file to add Git to your path automatically. Follow the instructions on my blog at this URL. It only takes a minute. Now I should be able to launch the Node.js command-line program from my Start screen. If running Git shows the help text, you've got everything working. In Visual Studio, I'll right-click CoinCounter, and choose Open Folder in File Explorer, then I'll copy the path from the address bar, open up my command-line, type cd, right-click, Paste, and now I'm in the CoinCountergame folder. We've come to where we need to make our first decision. CoinCounter is currently the only project in our Visual Studio solution. If we think that we'll only ever have TypeScript in this one project, we should set things up here. If we have other projects in our solution that use TypeScript or JavaScript, or think we may add more in the future, we should set up things in our solution folder. Since CoinCounter is a one shot, I'll set things up here. The first step is to create a package.json file. I already used npm to fetch QUnit, but I'll delete my existing package.json, and recreate if so you can see the process. I'll run the command npm init. Woops, okay, we're talking about practical TypeScript migration here and this is a bug in current versions of npm when you very first install it. It's really, really super annoying and I can't believe this is the very first thing that happens when you try to use it, but check it out, you've got to create a directory in this folder. I'm going to copy that path to that roaming folder, and run dir against it. Sure enough, there's not an npm folder in there. I'll create one with the md command, that should hopefully fix it. Npm init, okay. Anyway, this is a wizard for creating a package.json file. I can hit Enter if I'm happy with the default presented by each step or type my own value. The first question is what the name of the package should be. CoinCounterGame is fine, so I'll hit Enter. I'll accept the defaults for the sake of time, except that I'll enter the author field, and set the license to Pluralsight, and Enter for yes. The npm init command shows you the package.json that it created based on what I entered, and you can even see how npm noticed that QUnit was previously installed. Next, I want to install grunt-ts. This is the module that will compile our TypeScript using Grunt. Grunt is a popular JavaScript task runner that works great for build automation. Full disclosure, I'm a maintainer of the grunt-ts open source project, though I am not its original creator. To install grunt-ts, which will also automatically install both Grunt itself and TypeScript into our project, run npm install grunt-ts--save-dev. The save-dev part tells npm to edit our package.json file to include grunt-ts, that way the next developer to come along can simply run npm install, and they'll get all the required libraries. We'll document that later. The next thing we need to do is create a gruntfile.js, which is Grunt's configuration file. There's a starter one on the grunt.ts readme that I can just copy and paste in. The grunt-ts website is at github.com/typestrong/grunt-ts. If you scroll down in the readme, there's a minimalist Gruntfile. I'll copy it and then flip back to Visual Studio. Since I created package.json in the project folder, I'll create my Gruntfile there too, right-click, Add JavaScript File. I'll name it Gruntfile.js with a capital G, and paste it in the code that I copied from the grunt-ts website. I'll save the file. Note that if I had wanted to set up grunt.ts in the root of my solution, I could have created the Grunt files a new item by right-clicking on the solution. Before we run Grunt, let's talk little bit about what this Gruntfile does. The grunt.initConfig function takes an object literal that defines all the tasks that we might want Grunt to perform. The Config has a ts task defined with a default target. The default target has an src attribute, which is an array of strings. The strings are in the glob format, which is a common way of selecting files when using Node. This particular glob array is instructing Grunt to find all files with a .ts extension found in the current folder and subfolders, excluding any found in the node_modules folder. The exclamation point is for a logical not. Then we're instructing Grunt that it should load a task from the grunt.ts and pm module and that ts should be included in the default task. The bottom line is that if we run Grunt with this Gruntfile, by default it will compile all the TypeScript files in our project. You may be wondering why I didn't create this as a TypeScript file. I could have, but I haven't seen much benefit from doing that for Gruntfile. I do know that some people like to use CoffeeScript for their Grunt files because it offers a simpler syntax, but to me with TypeScript, it sort of creates a chicken and egg problem where we need to compile our Gruntfile in order to compile everything else. I think it's easiest just to leave our Gruntfile as JavaScript, and do everything else in TypeScript. By the way, the Grunt tasks we're going to call into to compile our TypeScript, grunt.ts, was itself written in TypeScript. So while I don't necessarily think that you should make your gruntfile into TypeScript, if you're going to write a Grunt task, certainly go ahead and write it in TypeScript, you'll get a lot of benefit from that. I'll flip back to the command-line and there's one more thing to do before I can run Grunt and actually have it work, but I want to show you what happens if you don't do that prerequisite. I'll type grunt and hit Enter. Grunt is not recognized. Okay, let's fix that. Once ever on a computer, you have to run a command to bootstrap the Grunt command-line interface, the command to do that is npm install-g, for global, grunt-cli. Grunt-cli is a stub that points to whatever version of Grunt is installed in your project, that way each project can have its own Grunt version if necessary. Upon installation, grunts-cli notes that it mapped the grunt command in my profile folder to the grunt-cli Bootstrapper. Now I should be able to run Grunt and it will execute the default task in my Gruntfile. Cool, Grunt used the file globs we provided to find 15 TypeScript files and compile them using TypeScript 1.4.1. If I run grunt again with a --verbose switch, it will show me even more information including the command-line it passed into tsc with the files and switches. I can tweak the configuration of how Grunt calls tsc by editing the options in the Gruntfile. If you look up here, we can see that by default grunt.ts tells tsc to remove comments from the emitted JavaScript. In the Gruntfile, I can add an options property and inside of that set comments to true. Now when I run Grunt, tsc doesn't get passed through remove comments flag and the comments are preserved. Now that we've got our TypeScript compiling, let's talk about bundling. Bundling and Minification with Grunt Now that we've got our TypeScript compiling, let's talk about bundling. I'll launch the app with Ctrl+F5 and open the browser F12 tools. In the tools, I'll select the Network tab and click the Play button to start logging, some browsers do that automatically, but IE makes you enable it. Now I'll refresh the page and see what network traffic is required to start our game. It looks like there were 30 HTTP requests, just over 9 KB uploaded, and 0.68 MB downloaded. There are 2 CSS files and 11 JavaScript files that come from our server. Eight requests are up to Google's static servers as a consequence of using the Open Sans web font. If I scroll down, seven other requests were for js.map files, which wouldn't actually load unless someone were trying to debug the site, so they won't be part of this optimization. Let's see if we can use Grunt to bundle up and minify some of these files. The first thing we'll do is get a Grunt task that can concatenate files. I'll run npm install grunt-contrib-concat --save-dev. Then I'll add a line in our Gruntfile to load the concat task. Now that the task will be loaded, I'll set up a default target for it. The src for this task will be our external libraries. If I open the Scripts folder in Visual Studio I can see the libraries there. And these all have to be specified to be in the Scripts folder. The files will be concatenated in the order specified. Some of our libraries depend on jQuery, which is why I put jQuery first. I'm going to keep the debug version of Knockout there to have a fair comparison. The debug version isn't minified, so it's only meant for use while developing. I've been using it all along. I want to leave it there for now so I can measure Coin Counter as it really is first. After measuring, I'll replace Knockout debug with the minified version and measure again, that way we'll be able to quantify any improvement. Now that I've identified those four files as the source, I have to identify the destination. I'll add the dest parameter and specify Built/vendor.js. The last thing I need to do is add the concat task to the default target. Now when I run Grunt, it will compile my TypeScript and then create a file called Built/vendor.js. (Typing) Cool. Let's open that file and check it out. I'll show all files, open the newly created Built folder, and open vendor.js. Oops, look at all those comments. I guess I didn't include the minified version of jQuery. Let me go correct that in the Gruntfile. (Working) We can see that jQuery, big.js, Bootstrap, and Knockout are all in here and in the correct order that we specified, awesome. Now let's change index.html to use Built/vendor.js and see if our counts are any better. (Working) Cool, looks like our counts are better. We had 3 fewer HTTP requests and about 1 KB less data sent from the browser. Our total bytes downloaded was about the same because we still fetched the same data, it just came in one big chunk instead of separately. Off camera, I tested it again using the minified Knockout library instead of Knockout.debug and our page size dropped again by about 200 KB. It goes to show that sometimes small things can in fact significantly affect web performance. Now let's see if we can do something about our application's JavaScript files. Concatenation of already minified vendor scripts is one thing, but I'd like to demonstrate how we can minify our own JavaScript. What is minification anyway? Well it's a way to compact the JavaScript file into the smallest possible size that still has the same functionality. Minifiers use clever tricks to shrink the size of JavaScript files significantly. Let's run our JavaScript through the concat task first just to get a baseline and then we'll see how much can be improved. In the Gruntfile, I'll rename the default target under concat to vendor, then in the default task I'll specify that it should run concat:vendor. This means that I can now add another target under concat, we'll call that coinCounter. I'll add an src property and assign it *.js, that will search for any JavaScript files in the current directory. Be careful though, our Gruntfile's here too, so we'll have to add !Gruntfile.js. It's important to be aware of what you're specifying in the globs, particularly if a source glob could pick up what's in the destination. The destination can be Built/coinCounter.concat.js. That won't be picked up in our glob because it's not searching in subdirectories. I'll add concat:coinCounter to the default task and run run. (Working) Now we've got a coinCounter.concat.js file that we can add to index.html. For now, I'll just comment out the original script tags and add a new script tag for Built/coinCounter.concat.js. Let's launch the app with Ctrl+F5. I'll press F12, open the Network tab, press Play, and refresh the browser. Our baseline is 16.92 KB, that's the size of the coinCounter.concat.js file. Let's go back to the command-line. To minify our JavaScript, we'll use a library that I think has one of the best names out there, Uglify.js. We'll install the Grunt helper for Uglify by running npm install grunt-contrib-uglify --save-dev. Now let's update our Gruntfile again. We'll load the npm tests for Uglify and then create a new config entry for it. We'll create a coinCounter target under uglify, and copy the configuration from our concat task. Concat coinCounter can be removed now. Then we'll change the dest to Built/coinCounter.min.js. Finally, we'll put Uglify in our default task. Let's run Grunt. Okay, one file created. Now we can update our index.html file to reference our minified file, and check it out in the browser. CoinCounter.min.js is 8.15 KB, that's less than half of the 17 KB in our original concatenated file. Way to go Uglify, not bad. We just made some fairly significant optimizations to our JavaScript delivery. Next, let's improve our development workflow by automating our unit tests. Automating Unit Tests, TSD, and grunt-ts Visual Studio Support In this clip, we're going to automate QUnit with Grunt. From the command-line I'll run npm install grunt-contrib-qunit --save-dev. The grunt-contrib-qunit package includes PhantomJS, which is a headless WebKit browser. That means you can launch and use the browser from the command-line without needing a UI. Let's tell Grunt to run our unit tests using PhantomJS. Back in the Gruntfile, I'll tell Grunt to load the grunt-contrib-qunit npm task, which was just installed. Then I'll add a configure entry for QUnit. In the default target, we'll create an options property and specify the URL to our test page, http://localhost:8000/tests/tests.html. Wait a minute. What's that port 8000? We don't have a web server set up there. We don't? Okay, well let's have Grunt start one up temporarily. Back to the command-line. I'll run npm install grunt-contrib-connect --save-dev. Connect is a web server for Node.js. With the grunt-contrib-connect package, Grunt will launch the connect HTTP server so that we can run our tests, and will terminate connect once Grunt is completed. Back in the Gruntfile, let's add the line to load the grunt-contrib-connect npm task, I'll be you're sensing a pattern here, then I'll need to add a config entry for connect. In the default target, I'll add an options property. I need to specify a port and a base for the web server. Dot is fine for the base meaning the same folder as the Gruntfile. Then I need to place connect and QUnit into the default Grunt task, connect needs to come before QUnit because of course we need to start the web server before we can run our tests. Let's run Grunt. Woops, looks like I goofed up my Gruntfile. Yep, I didn't properly close my curly braces on line 42. Let's try again. (Running) Testing. Hey, it worked. 30 assertions passed. Let's mess up something just to see how it looks. I'll go into gameclocktests and change the test on line 14 to say that GameClock should be running before it's started, then I'll run Grunt again and see what happens. See that little F? Cool, sure enough, upon a test failure, it shows what test was running, the expected message on the assertion, and what the actual and expected results were. Cool stuff. I'll go ahead and fix that test back to being correct. Another Node.js tool that's complimentary to TypeScript is TSD. TSD is the command-line alternative to using NuGet to manage TypeScript definitions from DefinitelyTyped. TSD is helpful if you have team members that aren't using Visual Studio or if you just want to standardize on using Node to manage TypeScript. The first thing I'll do is remove all the DefinitelyTyped packages that were installed using NuGet. First, I'll uninstall the big.js DefinitelyTyped definition, then Bootstrap, this one says that it depends on jQuery. I'll go ahead and uninstall that too. Next is Knockout, and finally QUnit. Now that our definitions are gone, TypeScript says that we have 79 errors in our project. I'll open up the Node.js command prompt again. The first thing I'll do is install TSD globally. The command is npm install -g tsd. You might see some errors if you don't have Python installed, don't worry about that, it's an optional dependency. The next thing I'll do is run tsd init. Similarly to how npm init works, this will create a file called tsd.json in the current folder. The way to search for a definition with TSD is by running the query command, for example, I can type tsd query big.js. When I run that, TSD goes up to DefinitelyTyped on GitHub and then prints out any matching libraries. In this case, there's only one. Be aware that the timestamp it shows is the time of the latest commit to DefinitelyTyped altogether, not the latest timestamp for the big.js definition. To install the library, run the same command, but with some extra parameters, tsd query big.js -a, for action, install -s, for save. TSD downloaded the definition file from GitHub and updated our tsd.json file. I'll add that file to our project. (Working) In the tsd.json file, it now lists the definition that we're using and will commit to the DefinitelyTyped repo that it came from. It also mentions this tsd.d.ts file, I'll add that file to the project too. When you install a definition using TSD, it gets added in this file automatically. If there's this file is referenced in your project or on the command-line, any definitions you obtained using TSD will also be referenced automatically and you don't need to bother adding them to your project. Let me reload the project with our macro. Notice our error count now is down to 67, that's because the big.js errors went away. I'll go back to the command-line and install the remainder of our definitions. JQuery, knockout, bootstrap, and qunit. Now when I reload my project, all the errors go away. When it comes time to update a definition obtained by TSD, you have two choices. If you want to update a specific definition, you have to run the same command as you'd run to perform an install, except add an O for Overwrite. There's no space required between the S and the O. If you want to update all definitions to the latest version, you can run tsd update -so. One final command that's useful is if you don't actually check in the definitions to your source control, you could refresh the definitions to the Git commit specified in the tsd.json file by running tsd reinstall -so. There's one last feature of grunt-ts that I'd like to show you. In addition to the normal Grunt target settings like src and files, the grunt.ts task allows you to fetch the files and TypeScript compilation settings identified in the Visual Studio project. Instead of using the src glob, I can specify the vs property and point it to our csproj file. Now when I run Grunt, it'll compile using the settings specified in CoinCounter's current Visual Studio project configuration. This works even on computers that don't have Visual Studio installed like for folks on a different OS, team members with a different editor, or even if you're running grunt-ts on a build server. Grunt-ts also lets you override or ignore the project settings so you can take what you want and customize the rest. For example, under options we have comments set to true. With this option in the Gruntfile, regardless of how the Visual Studio project was set up, Grunt would instruct the TypeScript compiler to preserve the comments. This functionality is fully documented in the grunt-ts readme, including instructions on how to disable the Visual Studio TypeScript build altogether while keeping the language service active. This can be useful if you decided to standardize on a command-line build for your TypeScript and you want to avoid a double compilation. Repeatable Builds on a Team At the beginning of this module there was something I promised that we haven't gotten to yet, and that was to make the build process repeatable for another developer on your team or for yourself if you ever rebuild your computer. To do that, we've got to talk about source control, package.json, and everyone's favorite text file, readme.txt. The first thing I want to mention is a housekeeping subject is source control ignores. Once you're using npm, it's standard to ignore the node_modules folder. Some people feel uncomfortable doing that because they want to have everything it takes to build their project inside source control. If that's the case, I'd still recommend ignoring node modules, but to solve the issue, setting up a private npm registry instead. Another thing you want to ignore is the .tscache/ folder, which is used by grunt-ts. Finally, with the way we set up Grunt, our deployment artifacts are copied into the Built folder. As a result, we'll want to ignore the Built folder in source control too. Keep an archive of anything you actually deploy in a separate system like a continuous integration tool. Once all that's done, let's be absolutely sure to check in the new readme.txt file that explains the steps required to repeat our build on a new machine. It should say something like this, Once per machine, do the following: Install Node.js from nodejs.org, Install Git and make sure it's in your path, Run npm install -g grunt-cli, that's the bootstrapper that makes grunt work, then Run npm install -g tsd, that's the DefinitelyTyped command-line tool. Once per repository, do the following: Clone the source, Open the Node.js command prompt and navigate to the same folder as package.json, Run npm install, Run tsd reinstall -so, To build and run unit tests, run grunt. That's it. Since we saved all the dependencies in our package.json file when we ran npm install for each library, the next person to come along just has to run npm install and they'll get everything. Very cool. Before we wrap up, I wanted to mention that there's a ton more we could do with Grunt for CoinCounter. I just wanted to show you some basic stuff to get started. Two libraries that I really ought to mention are Nodeunit, which is a testing library for Node.js modules, and TSLint, which is a linter for TypeScript code that integrates nicely with Grunt. Linting lets you programmatically enforce TypeScript coding standards like disallowing trailing whitespace or forcing class names to be capitalized. Some improvements to our Grunt build script that would be useful are minifying and bundling our CSS files, minifying our HTML, setting up the tests to work against the minified JavaScript file, and getting our TypeScript source maps to survive minification, that would let us do debugging in the browser's F12 tools, even if we were using a minified JavaScript file. I'll leave those activities as exercises for you, or maybe you'll even try to get some of those things working in your own projects. If you want to learn much more about Grunt, there's a great course on Pluralsight called Build Process, Workflows, and Tooling with Grunt.js and Beyond by David Mosher. He covers things in way more depth than I have in this brief demonstration. Well, I think that's all I've got. I hope you've seen that TypeScript is approachable and that it can improve your JavaScript development experience. I've shown the techniques necessary to convert an existing JavaScript code base to TypeScript and identified some places where TypeScript still has some rough edges. We covered team and project subjects like source control and picking where to get started. We also took a look at using Grunt and npm packages to create a simple build system that runs on Node.js. I'm Steve Ognibene. I'm on Twitter at NYCdotNet. I hope that after watching this course you'll be excited and feel prepared to start a practical TypeScript migration of your own. Thanks so much for watching. Course author Steve Ognibene Steve Ognibene is an application developer in New York City specializing in SQL Server, C#, VB.NET and TypeScript. Steve is an active contributor to open source projects and is the author of the... Course info LevelIntermediate Rating (126) My rating Duration2h 21m Released17 Apr 2015 Share course