TypeScript In-depth


  1. Why Use TypeScript? I just gave you a couple of reasons you might consider TypeScript for your next project, but I want to quickly cover some of the specific benefits of TypeScript. The first is that it's a superset of JavaScript. This will greatly simplify the transition to TypeScript for developers that have even a passing familiarity with JavaScript. It also means that any JavaScript you can get your hands on is already valid TypeScript. The types in TypeScript make your code safer. You'll have fewer bugs, and fewer bugs means happier users. The JavaScript language has a handful of types like string, number, and Boolean, but TypeScript lets you define your own types in a very object-oriented manner, and the compiler will then check your code against those types and alert you to problems long before it gets to a production environment. I happen to believe that the addition of types also enables faster development. If you're using a TypeScript-aware editor, it becomes a lot easier to examine the properties and methods available in custom types, and navigate around your project based on the symbols declared in your code. The best part about TypeScript is that it compiles to plain-old JavaScript that runs everywhere. The latest versions of TypeScript can compile down to the ES3 version of JavaScript, ES5, which is currently supported by most modern browsers, and ES6, which is officially known as ES2015. The ES is short for ECMAScript, and refers to the official scripting level specification which JavaScript implements. TypeScript is cross-platform. For most of this course I'll be developing on a Mac, but TypeScript also works great on Windows and Linux. Lastly, TypeScript is open source. It was originally developed by Microsoft, and it's now maintained by the company as an open source project on GitHub.

  2. Course Modules and Demo App There are very few prerequisites for this course. It would be helpful if you have a basic understanding of JavaScript, but I'll be writing code exclusively in TypeScript and explaining it all as I go, so don't let a lack of JavaScript experience deter you from continuing. I will assume that you have Node.js installed on your computer. Node is a JavaScript runtime environment, and I'll be using it to install TypeScript and to run the TypeScript programs I write after they're compiled to JavaScript. Node is free, open source, and runs on Macs, Windows, and Linux. You can download it from nodejs.org. The final thing that would be helpful, but not required, as you progress through the course, is an editor that understands TypeScript. Thankfully there are lots of great choices, and some of them are even free. I'll primarily be using Visual Studio code in this course, but in the next module I'll walk you through configuring several different options, including Visual Studio, Sublime Text, and WebStorm. Before I go any further, I want to give you a very quick overview of the modules in the course. In the next module, I'll show you have to install TypeScript and configure several different editors for TypeScript development. You can feel free to skip the clips in the module related to the editors you don't plan to use. After that will be a module covering some TypeScript basics such as variable declarations and common data structures. Next we'll move into a series of modules devoted to specific language features. There are modules on functions, interfaces, classes, modules and namespaces, and generics. After that will be a module covering compiler options and how to configure your TypeScript projects. I'll wrap up the course with a module showing you how to use type definitions, which are a tool for letting you use JavaScript libraries in your TypeScript projects. Throughout the course, I'll be demonstrating TypeScript language features while building the shell of an app I've named Library Manager. The idea is that it will be an application that could be used for managing a library and the things and people in it. I'll create types for, and write code that uses entities like books, authors, librarians, and magazines. I want to keep the focus on TypeScript and not have you get distracted by all of the extra stuff that comes along with a complete web application, like HTML, CSS, server-side code, and databases. The code I write in the Library Manager app will be very simple TypeScript code that I'll compile to JavaScript and use Node to execute, either in a terminal or inside the console of my editor. Okay, I think that's enough introductory material. Let's get started by installing TypeScript in the next module.

  3. Installation and Setup Introduction and Overview Hi. This is Brice Wilson. Welcome back. In this module, I'm going to cover the very basic things every developer needs to do to get started writing TypeScript code. This includes installing TypeScript, as well as selecting and configuring your development environment. There are lots of editors that provide excellent support for TypeScript, and I'll show you how to configure, as well as write and compile TypeScript code in several of them. I'll start things off with a quick demo showing you how to install TypeScript. It's a very straightforward process and only takes a minute once you have Node and npm installed. I'll then go over some of the very good options available for editing TypeScript code, and walk through the process of using several of the most popular editors. I'll show you how to get started with Visual Studio, Sublime Text, WebStorm, and Visual Studio Code. Let's get started by installing TypeScript.

  4. Installing TypeScript There are two primary ways to go about installing TypeScript. The first is to install an extension to Visual Studio if that's where you intend to write your TypeScript code. The other option is to use npm. In this demo we'll take a look at where to go get the Visual Studio installers and how to install with npm. Installing TypeScript is pretty simple, but there are a couple of different ways to do it. I'm here on the TypeScript website, which is obviously a great place to start when you're looking for something TypeScript-related. I'll move my mouse to the download menu at the top. I'll just hover over it, and we're shown several options for downloading TypeScript. The first is to use npm, which is the Node Package Manager. Here it's showing us the npm command we can use to install TypeScript. We'll run that in just a minute, but let's look quickly at the other options first. The next two choices are links to download the latest version of TypeScript for VS2013 and VS2015. These are links directly to the downloads for those packages on the Microsoft site. If you plan to work with TypeScript from within Visual Studio, then you definitely want to install one of these packages. Visual Studio 2015 comes with TypeScript, but this download will make sure you have the latest version. The last option in the list is a link to the TypeScript repository on GitHub. TypeScript is maintained by Microsoft, but it is open source and you're free to grab it from there as well. If you're not using Visual Studio, installing TypeScript with npm is probably going to be your best bet. npm gets installed when you install Node.js. I had the Node website open in my other browser tab. If you're not familiar with Node, it's a JavaScript runtime that has become quite popular for running server-side applications written in JavaScript. Since TypeScript compiles to JavaScript, Node is a very natural environment for running applications written in TypeScript. npm is the Node package manager and is used to install packages used in Node and Web development. I'll be using Node and npm in this course to install TypeScript and to run the programs we write with it. They have both become very important tools for modern web development, so if you don't have them installed already, this would be a great time to do it. Node and npm run on Macs, Windows, and Linux, and you can find all of the different versions by clicking the downloads link here on the home page. I've already got them installed here on my Mac, so I'm going to open a new terminal window and show you how to use npm to install TypeScript. It's very straightforward. To install any npm package, you start by typing npm install. I want to make TypeScript globally available on my machine, so I'm going to add the -g flag. The last thing we add to the command is the name of the package we want to install. In our case that will be TypeScript. I'll hit enter, and you can see some output letting us know it's been installed. You can see the TypeScript version listed in the last line of the output, but if you ever want to know what version of the TypeScript compiler you're using, just type tsc -version, which can be abbreviated tsc -v. tsc is the TypeScript compiler, and we'll see how to use it with lots of different options throughout the course. We can see that I'm now running version 1.7.3. To see all of the options you can pass to tsc, as well as a couple of simple examples, you can type tsc -help. I'll scroll up just a little bit, and you can see the help output gives us a simple example of how to compile a TypeScript file to JavaScript. Below that are lots of compiler options you can use, which we'll take a look at in a later module. Let's now talk about some of the options available for editing TypeScript code.

  5. Choosing an Editor As TypeScript has grown in popularity, more and more editors provide a great TypeScript experience. Most provide very good support for code completion and syntax highlighting, some will compile your code for you, and a few will even let you debug your TypeScript. TypeScript was developed by and is maintained by Microsoft, so as you might expect, Visual Studio and Visual Studio Code are both excellent TypeScript development environments. Visual Studio has been around for many years and only runs on Windows. Visual Studio Code is a relative newcomer, but it is fast, light, and runs on Mac OS X, Windows, and Linux. Sublime Text is a very popular editor with a huge ecosystem of plug-ins built to do just about anything you might expect an editor to do. The TypeScript team at Microsoft built and maintains a plug-in for Sublime that turns it into an excellent TypeScript editor. WebStorm is popular among JavaScript and frontend developers, and includes very good support for editing and compiling TypeScript code. There are also plug-ins for Atom, Vim, and lots of other editors, so if your preferred editor is not on this list, just do a quick Google search. It's very likely you'll find an add-on with at least some support for TypeScript. In the next few clips, I'm going to quickly show you how to get started using TypeScript in several different editors. I'll show you how to configure them to work with TypeScript, and I'll write a quick Hello World program in each of them to give you a sense of the code completion and compilation experience in each. I'll start with Visual Studio, which requires very little configuration. We'll then take a look at Sublime Text, and how to install and use the plug-in developed by the TypeScript team. I'll then show you the very good experience WebStorm provides right out of the box, and I'll wrap up with a somewhat more detailed look at Visual Studio Code. Feel free to skip the clips covering the editors you don't plan to use, however, I would recommend watching the last one on Visual Studio Code, since that's the one I'll be using throughout the remainder of the course. First up is Visual Studio.

  6. Using Visual Studio Visual Studio provides an excellent TypeScript development environment. We saw in an earlier clip how to install TypeScript, but I wanted to point out once again that the download menu on the TypeScript site has links to the TypeScript extensions for both Visual Studio 2013 and Visual Studio 2015. Once you have those installed, you have everything you need to write and compile TypeScript code with Visual Studio. However, there is one more Visual Studio package I want to show you that I think greatly enhances writing simple programs to experiment with the language. The Node.js tools for Visual Studio is a great add-on for any developer working with Node, but it also includes some additional project templates that make it easy to experiment with TypeScript without the overhead of creating an entire web page or application just to host your compiled JavaScript code. In my other browser tab, I've got the VisualStudio.com website open. We can get to the section for the Node tools by clicking on Features at the top of the page, and then choosing Node.js from the application development submenu. From this page you can learn all about the Node Tools for Visual Studio, and the link here at the bottom of the page will download the package. In the rest of this course I'll be using a Mac, but for this clip I'm going to use Visual Studio 2015 installed on a Windows 10 machine. I've already installed the Node Tools, so let's write a simple Hello world program to show the benefits provided by the Node Tools, as well as the great TypeScript experience you get with Visual Studio. I'll go to the File menu and start a new project. We see the normal list of project templates we can choose from. I'm going to collapse the C# templates, and closer to the bottom I'm going to select the section for TypeScript templates. I'll expand it, and you can see that there is a group of Node.js templates which were installed by the Node Tools package. I'll select the Blank Node.js Console Application template. I think console applications are a great way to experiment with language features without getting bogged down creating and managing fancy user interfaces. I think console apps give you a simple way to try things out and writing output to the console is usually adequate for seeing how your code is behaving. I'm going to name our new app HelloTypeScriptVS. I'll hit enter, and Visual Studio creates the project for us. The template creates a very simple project with a single code file named app.ts. Right now that file contains one line of code that just writes Hello World to the console. Let's start by building this project exactly as it is. I'll go to the Build menu and choose Build Solution. When it's done building, you can see that we now also have an app.js file in the project. It contains the JavaScript that was output when the TypeScript was compiled. Since there was nothing very specific to TypeScript in the file, the JavaScript that was output is identical with the exception of a reference to the map file at the bottom. One of the benefits of writing TypeScript in Visual Studio is that with no additional configuration it will automatically compile your TypeScript files every time you save them. To see an example of this, I'm going to open the output JavaScript file beside the source TypeScript file. I'll close the Solution Explorer just to make a little more room. I'll now change the TypeScript file to say Hello TypeScript instead of Hello World. Now as soon as I save that change you'll see that the JavaScript file is immediately updated. Let's now write a slightly more advanced version of Hello World that will demonstrate some of the TypeScript editing capabilities provided by Visual Studio. I'll delete the single console statement we have now and add a class to the file named HelloWorld. Don't worry if you don't yet understand all the syntax in this example, we'll cover all of it and lots more throughout the course. I'll add a constructor to the class, and you can see as I start to type the word constructor, Visual Studio recognizes that as a TypeScript keyword and offers to complete it for me. It does the same thing as I add a public parameter toe the method that as a data type of string. I'll then come down a couple of lines and declare a new variable named Hello, and assign to it a new instance of our HelloWorld class. As I start to type HelloWorld, Visual Studio, again, recognizes that as a class in our code and offers to complete it. It also knows that it expects a parameter named message that is of type string. I'll pass it the string Hello TypeScript. I'll then log that message to the console. Notice that as I type console.log, Visual Studio continues to give me helpful code completion hints, including when I reference my new Hello variable inside the log function. I'll now save the file, and again, Visual Studio immediately compiles it, and you can see the JavaScript output in the other code editor. Since this is a Node console application, I can see the output by just clicking the start button on the Visual Studio toolbar. That opens a new console window where Node executes the compiled JavaScript. As we expected, it output Hello TypeScript. I think this enables a very nice workflow that allows you to experiment with TypeScript without having to build an entire web application. As a side note, the Node project templates are also great if you want to build actual production-quality Node applications. Imagine that?

  7. Using Sublime Text Sublime Text is a fast and powerful text editor that has become very popular over the last few years. It's quite extensible, and there are many thousands of plug-ins available for it. Because of this popularity and extensibility, the TypeScript team at Microsoft developed their own TypeScript plug-in for Sublime which provides excellent support for writing and compiling TypeScript code. I've got another browser tab open to the GitHub repository for the plug-in. You can find it by searching GitHub for TypeScript-Sublime-Plugin. I'll scroll down to the README. You can see in the Requirements section that the plug-in requires Node to run the TypeScript server. The TypeScript server provides information to the plug-in to facilitate code completion. A little further down there is a section on how to install the plug-in. There are two options listed. The first is to use Package Control, which is a popular package manager for Sublime Text. The second option is to use Git to clone the plug-in repository right into the Sublime Packages folder. I'm going to use Package Control. I've got the Package Control website open in another browser tab. It's a great tool that makes it very easy to install lots of different plug-ins for Sublime. You can find the instructions for installing it by clicking the Installation link on the right. I've already got it installed, so I'll now jump into Sublime and use it to install the TypeScript plug-in. I'm using Sublime Text 3. I'll open the Sublime command palette by pressing Command Shift P on my Mac. That would be Ctrl Shift P on Windows. I'll then type the word package to search for the available Package Control commands. I'll select Package Control Install Package. That brings up another window that lets me search for the package I want to install. I'll start to type the word TypeScript, and it filters the list based on what I type. It found the package. It's now the first one in the list, so I'll just hit Enter to install it. When it's done, you'll get a message in the status bar letting you know it installed successfully. I'll now go over to my terminal and create a directory for our new Hello World application. I'll call this one HelloWorldSublimeText. I'll go into that directory and then use the Sublime command line tool to create and open a new file named hello_world.ts. The file has a ts extension so the plug-in will recognize it as a TypeScript file and help us out as we type. I'm just going to write the same HelloWorld program I wrote in the earlier Visual Studio example. You can see it recognizes all of the TypeScript keywords like class and constructor, and makes it pretty easy to type code. Once I have my new class defined, it also recognizes it and gives me code completion help with it as well. The plug-in also includes the ability to compile our TypeScript code to JavaScript. I'll just press command B on my Mac, Ctrl B on Windows, and it opens a box at the bottom of the window where I can enter build parameters for the TypeScript compiler. I'm going to add --target es5 and --watch. The --target es5 tells TypeScript that I want to compile my code into ECMAScript 5, which is the version of JavaScript currently supported by all browsers. The --watch tells the compiler to watch for new changes to my TypeScript source file and automatically compile them whenever the file changes. I'll hit Enter, and you can see I get a little status window at the bottom, letting me know that the compilation is complete and the compiler is watching for any new changes to my source file. To test the code, I'm going to go back over to my terminal window. You can see my folder now also contains the JavaScript file the compiler created. I'll run that file with Node by just typing node hello_world.js. As we would expect, it outputs Hello TypeScript. To demonstrate how the compiler is watching for additional changes, I'll go back to Sublime and add a new line of code that just outputs Hello Sublime. As soon as I save that change, you can see that I get a couple of new messages in the status window. The compiler detected the code change and successfully compiled it. I'll go back to the terminal and run the same node command again, and we can see that it now also outputs Hello Sublime. As you can see, the TypeScript plug-in works very well and is a very good TypeScript development option, especially if you're already a Sublime Text user.

  8. Using WebStorm WebStorm is a full IDE that provides good support for a number of frontend technologies, as well as Node.js server applications. It also includes support for TypeScript right out-of-the-box. Just to demonstrate a few of those features, I've got a new empty folder already opened in WebStorm version 11 named HelloWorldWebStorm. I'm going to start by adding a new TypeScript file to the project name, hello_world.ts. Notice that when I create the TypeScript file, WebStorm asked me at the top of the file if I want it to compile TypeScript to JavaScript for me. On the right side I can choose, OK, No, or Configure. I'm going to first choose Configure, just to show you some of the TypeScript options that are available. You can see that clicking Configure opens the WebStorm Preferences into the Languages and Framework section, and automatically selects TypeScript. On the right side, you can see some of the options you can specify such as whether or not to use a tsconfig.json file, which we'll cover later in the course, as well as the path to Node on your machine. For now I'm going to cancel out of this screen and choose OK to the original prompt to let WebStorm compile the code for me. Notice that when I do that it automatically opens the TypeScript Compiler pane at the bottom of the window. It's going to give us feedback about the compilation process as we're typing our code. To see that, as well as some of the TypeScript code completion support in WebStorm, I'm going to start typing the same HelloWorld program I've used before. You can see, like the other editors, it recognizes many of the TypeScript keywords and allows me to easily complete them. Also notice that as I'm typing it's attempting to compile my code in real-time. In this case I'm not even through typing this line, so I obviously have some errors. You could hide that pane if you find such immediate feedback distracting. I'll finish typing the program, save the file, and you can see that all of my errors are gone. There are a few other features of the Compiler pane you may find useful. The buttons on the left side let you start various compiler actions. You can also open the Console tab to see all of the output messages generated during the compilations. You can see the files output by the compiler by going up to the Project window. There is now an arrow beside the hello_world.ts file. I'll expand the arrow, and you can see that the compiler generated a JavaScript file, as well as a source map file, and that WebStorm helpfully nested them under the TypeScript file just to keep things nice and tidy in the project window. There are lots of ways to configure WebStorm to run the code you write with it. I'm going to keep things simple for now and just run it from a terminal. I could go out to my max terminal and run it from there, but WebStorm actually includes its own terminal window. I'll click on it next to the TypeScript Compiler pane and then run the program by typing node hello_world.js. It runs as expected. WebStorm is definitely another excellent TypeScript development environment worthy of your consideration.

  9. Using Visual Studio Code In this quick Visual Studio Code demo, I'm going to start by creating the directory for the project I'll use throughout the rest of the course. I'll start here in the terminal and create a new directory named LibraryManager. I'll go into that directory and then open Visual Studio Code at this location by typing code followed by a period. The default view is the Explorer view, which you can get to at any time by clicking the top icon here in the sidebar. It currently has opened the LibraryManager directory I just created, but it doesn't contain any files yet. I'll hover my mouse over the directory name and click the first little icon that appears to add a new file. I'll name it app.ts. I'm going to eventually use this file to begin writing the code for the LibraryManager app, but right now I'm just going to build the same quick Hello World program I demonstrated with the other editors to show some features of Visual Studio Code in a simple workflow you can follow when using it to write TypeScript. You can see as I start typing that it provides excellent code completion help for both TypeScript keywords and classes and variables I create. Visual Studio Code includes a built-in task runner. It can also hook into other task runners like Grunt and Gulp, but I'm just going to use the built-in features right now to create a task to compile the code in the project. I'll start by opening the command palette by typing Command Shift P on my Mac. That would be Ctrl Shift P on Windows. And then type the word task to see all the task-related commands I can run. I'm going to choose Run Build Task, which you can see can also be invoked with the keyboard shortcut Command Shift B. When I select that command, I'm told I don't currently have a task runner configured for this project. I'm going to fix that by clicking the Configure Task Runner button. That creates a new file named task.json and puts it in a new folder named .vscode inside our main project folder. It also opens the Task Output Window in a second pane to the right. I'm just going to close that for now. This json file can be used to create and configure tasks to do lots of different things inside Visual Studio Code. It contains one default task already that will compile TypeScript code. It also includes lots of comments, and samples, and other tasks you can create. Just to clean it up and simplify things, I'm going to delete all of the comments and samples we're not going to use. What we're left with is a very simple task that is configured to run the TypeScript compiler and compile one file with no compiler option specified. The command property tells us it will run the "tsc" command. There is no path to that command specified because, as the comment above it says, it assumes we installed TypeScript using the command npm install -g typescript, which I did. The next two properties just specify that the command is a shell command and that it shouldn't bother opening the Task Output window unless there are errors to report. The last property configures the default typescript problemMatcher. I'm not going to cover problem matchers right now, so we'll just leave that set to the default value. I am going to make some changes to the "args" property. It's an array of values that should be passed to the tsc command just as you would use them if you were running the TypeScript compiler from a terminal window. Right now it's configured to compile a file named HelloWorld.ts. That's obviously not what we want, so I'm going to change that. I'm going to use a couple of compiler options here that I didn't use in the previous demos. As a reminder, I'll cover compiler options in much more detail later in the course. Right now I'm going to use the target option and set it to "ES5." This specifies that we want the compiler to output ECMAScript 5 code, which is the version of JavaScript currently supported by most browsers. Next I'm going to use the outDir option to specify that I want all of the compiled code to be placed in a folder inside my project named js. This will just keep my project window a little tidier and give me a single place to get all of the compiled code if I later want to easily incorporate it into a deployment process. The next option I'm going to specify is the sourceMap option. This tells the compiler to generate source maps for all of the files it compiles. The source map files will create a mapping between the code in the original TypeScript file and the code in the compiled JavaScript file. This is particularly handy when debugging since your application will be executing the JavaScript file, but you want to debug and step through your TypeScript file. We'll see how to do that in just a minute. I'm going to use the watch option we've already seen so that the compiler runs in the background and automatically compiles our code when it sees changes to one of the source TypeScript files. The last thing I'm going to specify here is the list of files to be compiled. Right now I only have one file named app.ts. Okay, that's all we need to configure on the Build task right now. Let's run it and see if it works. I'm going to press command 2 to open a second editor window in Visual Studio Code. I'll then open the command palette and type output and select the command to Show Output. Now I'll open the Command palette again and select the same Run Build Task command I selected earlier. This time it sees that we have a build task configured and runs it for us. We can see in the Output window that the compilation was successful, and because I used the --watch compiler option it is watching for file changes, which it will compile automatically. We can also see in the project explorer that there is now a folder named js. I'll expand it and see that it contains the two files output by the compiler, the JavaScript file and its related source map file. I'll use the command palette to open the JavaScript file in the second editor. I'll then go back to the source TypeScript file in the first editor. Just to show that the files are being compiled automatically, I'll add another console.log statement at the bottom of the file. I have Auto Save turned on in Visual Studio Code, which is just an option you can check on the File menu. When the file is saved, the compiler runs automatically, and you can see that the JavaScript file is updated to include the second console.log statement. Let's now see how we can run and debug the TypeScript Code. I'll close the JavaScript file for now. I'll then click the Debug button, which is the bottom button on the sidebar. Similar to how we configured a task to compile the code, we now need to configure Visual Studio Code to run and debug the code. We do that by clicking the Configure icon, which is the little gear icon at the top of the screen. I'm immediately prompted to select a debug environment. We're going to run our app with Node.js, so I'll select that from the list. That adds another new file to our project. This one is named launch.json and is added to the .vs code folder right next to the task.json file. The default version of this file includes two different launch configurations. One is named "Launch" and the other is named "Attach." Those names then appear as selections in the dropdown box at the top of the Debug pane. I'm only going to change a couple of things in this file right now. The program property specifies which file to debug. I'm going to change that from app.js to app.ts. Node will actually execute the JavaScript file, but this is specifying that it's really the TypeScript file we want to debug. The source map file is what lets us configure it this way, and we tell the debugger to use the source map file by setting the sourceMap property in this configuration to true. Lastly, I'll specify that the output directory is js so that it knows where to find the JavaScript file to run. That's all I'm going to change in this file right now, however, I will point out that there is a property called "externalConsole", and it's set to false. The effect of that is that all console output generated by our program will be sent to the debug console built into Visual Studio Code. If I were to change that value to true, a new terminal window would open when I run this configuration, and all of the output would appear in it. For simple testing I like using the built-in debug window. I'll also mention that there's another property you can set on configurations that is not shown in this default setup named "preLaunchTask." You can use it to launch any task you have configured in Visual Studio Code before the debugger starts. That's another way you can make sure your code is compiled before launching the debugger. I'm not going to use it here because I used the Watch compiler option on our Build Task, which means the latest version will always be ready to run. Okay, I'll now go back to our source TypeScript file. We can launch it in the debugger by clicking the green arrow at the top of the debugger pane. It can also be invoked by pressing F5. It automatically opens the debug console, and as we would expect, we can see the result of the two log statements. I can stop the debugger by clicking the red square on the little Debug toolbar at the top. I can also stop it by pressing Shift F5. I'm going to run it again, but before I do I'm going to set a breakpoint on the first log statement. I'll press F5 to run it, and you can see that it stops on the new breakpoint. You can inspect local variables in the small window here at the top. It already contains the hello variable I declared, but I'm also going to add it to the WATCH window, just so you can see how to use it. I'll just right-click in the WATCH window and choose Add Expression, and then just type the name of the variable I want to watch. It lets me know that the hello variable is an instance of the HelloWorld class, and I can expand it to see that it has a property named message with a value of "Hello TypeScript." Next I'll use the buttons on the Debug toolbar at the top to step through the code and see it output the log statements as I step through each of them. Okay, that's a quick overview of some of the features of Visual Studio Code and how it can be used for TypeScript development. Let's now shift our focus more specifically to TypeScript and talk about the various ways we can declare variables and specify types.

  10. Summary Getting prepared to learn a new language always involves a few important preliminaries, and I tried to cover them in this module. We saw how to install TypeScript, as well as how to configure several editors to make writing TypeScript code efficient and even fun. With each editor we saw at least one option for compiling and running TypeScript code. You should now be all set to begin exploring and learning about the TypeScript language itself. In the next module, we'll cover some of the basics including variable declarations, type annotations, arrays, and enums.

  11. TypeScript Basics Introduction and Overview Hi. This is Brice Wilson. In this module we're going to cover some of the basic features of TypeScript, such as how to declare variables and types, and how to work with the central data structures like arrays and enums. You can't write code without variables, so we'll start by saying how to declare variables and constants in TypeScript. Every JavaScript developers is familiar with var, but TypeScript also includes the keywords let and const, which are part of ES2015. We'll see how they all work and the benefits of using one over another. You can't have TypeScript without types, so we'll also see how to specify types for both variables and functions, and how they help us write better code with fewer errors. I'll wrap up this module with a look at some of the basic data structures built into TypeScript. The language includes support for enums, and add some functionality to the arrays all JavaScript developers know and love. We'll also take a look at a specialized version of arrays known as tuples. Let's get started by seeing how to declare variables with let and const.

  12. Declaring Variables Anyone that has ever written JavaScript code is certainly familiar with the keyword var used to declare variables. It has some non-intuitive behavior that is often confusing to new JavaScript developers. ECMAScript 2015 introduced two new keywords for declaring variables and constants, and TypeScript supports them as well. They are the keywords let and const. Let is used to declare variables, and const is used to declare constants. The primary difference between the older var and the newer let and const, is in the scoping rules applied to identifiers declared with them. Variables declared with var are globally available in the function in which they are declared. Even if the variable is nested five levels deep in an if block, any piece of code in the function can access the variable. Let and const are scoped to the block in which they're declared. The block is generally defined by a set of curly braces. A block could be the entire body of a function, or it could be the body of a simple for loop. Variables declared with let and const will not be accessible outside the block in which they are declared. This should help reduce errors since it will be a little more obvious where a particular variable can and should be used. Variables declared with var are hoisted to the top of the function in which they are declared. What this means is that even if a variable is declared at the end of a function, the runtime behavior is that it will be treated as if it were declared at the top of the function. Declarations made with let and const are not hoisted to the top of their container block. They are accessible only where they are declared. Another difference is that it's possible to declare the same variable name twice inside the same function using var. I would argue that's not something you should ever do, but thankfully if you use let and const you won't even be allowed to do that. Names may only be declared once in a given code block. Let's look at a simple example that demonstrates the new scoping rules that apply to let and const. In this function I've got an if block. Inside the if block I've declared two new variables. I used var to declare the variable named foo, and assigned it a string reminding me I can use it anywhere in the function. I declared the variable var with the new keyword let and assigned it a string reminding me that it's only available inside this block. The block in this case is defined by the curly braces that wrap the if statement. Outside the block, I'm going to attempt to log the values of the two variables I declared. The first statement will work just fine since foo was declared with the var keyword. The second statement here will generate a compiler error because TypeScript will not recognize the var variable since it was not declared in this outer block defined by the function.

  13. Basic Types and Type Annotations Let's now review the basic data types built into TypeScript. They match very closely what you are probably already used to in JavaScript. It includes the Boolean type, which can store true and false values, the Number type is just like JavaScript, a floating point number, Strings store text data. Arrays are also available. There are a couple of different ways to declare arrays in TypeScript, and you can even specify a type for the values the array will contain. We'll look at arrays more closely later in this module. TypeScript also includes support for enumerations with the Enum keyword. Enums are a way to give friendly names to a finite set of numeric values. We'll also look at them a little more closely later in this module. The Any keyword in TypeScript is used to denote that the variable can refer to any type. Declaring a variable with Any effectively gives you the same behavior you're probably used to with JavaScript. The variable could be assigned a string value on one line, and a numeric value on the next line, and some object value on the line after that. In general you want to avoid using the Any keyword if you want to take full advantage of the typing benefits offered by TypeScript. The last type on this list is not really a type at all. The Void keyword is used to specify the absence of a type. It's most often used to specify that a function does not return a value. When you declare variables in TypeScript you can specify the type of data that may be stored in the variable, however, it's not required that you specify a type. If you don't specify one, TypeScript will infer one based on how you used the variable. In this first example, I've declared a variable named myString. I haven't specified a type for it, but I did initialize it with a string value. Based on that, TypeScript will infer that the type of the new variable is a string. If I were to subsequently try to store a number in that variable I would get a compiler error. In this example I have a simple function that returns a number, however, I did not explicitly specify a return type for the function. TypeScript just infers that it will be a number based on the fact that the return statement in the body of the function currently returns the number 42. If I then declare another variable that TypeScript will infer to be of type string and try to assign it the return value of the ReturnNumber function, we'll get a compiler error because TypeScript knows the function returns a number and we're trying to assign that number to a string variable. Let's now take the same sample code and add type annotations to it so the compiler doesn't have to infer the types. On the first line of code I've added an annotation to declare that the myString variable will contain a string. You add a type annotation by placing a colon after the variable name, and then add the data type of the variable. The syntax for specifying the return type of a function is similar. You add a colon after the closing parentheses that surrounds the function parameters, and follow that with the return type of the function. Here I've specified that the ReturnNumber function will indeed return a number. The last declaration at the bottom is just like the first one. I add a colon after the variable name and specify that it will store a string. Let's now jump into a demo and experiment with variable declarations.

  14. Demo: Variables and Type Annotations In this demo we'll experiment some with variable declarations and type annotations. We'll do this as we add the first couple of functions to the library manager app we'll be building throughout the course. I'm back here in the app.ts file I created in the last demo. We're not going to use this HelloWorld code anymore so I'm just going to delete all of it. The first thing I want to do for the LibraryManager app is create a few book objects for us to work with. You can't have a library without books. I'm going to write a simple function named GetAllBooks. I'll cover functions in detail in a later module, but the ones I'll write now look and act just like any simple JavaScript function. I'm going to declare a variable named books and assign to it an array containing object literals that represent books. I'm going to use a code snippet to paste in the book objects just so you don't have to watch me type so much. Right now we have the smallest library in the world, it only contains three books. Each book in the array has three properties, title, author, and a Boolean property named available that specifies if the book is currently available to be checked out of the library. After assigning the array to the variable, I'm just returning the variable from the function. Note that I declared the books variable with let. In this particular case, it will behave just as if I had declared it with var since the block that contains it is the function body, and I declared it at the top of the function. I'm now going to add a second function named LogFirstAvailable. It will accept an array of books as a parameter, and log the number of books in the array and the first one it finds that is available for checkout. I'm going to use let to declare a variable to store the number of books in the array. Since I know I'll be passing an array to the function, I'll use the length property which exists on arrays to initialize the numberOfBooks variable. I'll use another code snippet to paste in a for of loop that will loop over the array of books looking for the first one with the available property set to true. currentBook will be the variable used to represent the book being examined in each iteration. Since I declared it with let, it will only be available inside the loop, which is defined by the curly braces after the for statement. Inside the loop, I'll declare a new variable that will store the title of the first available book, and I'll initialize it to an empty string. I'll then examine the available property of the current book. If it's true, I'll assign its title to the first available variable I just declared, and then break out of the for loop. Outside the loop I'm going to add a couple of console.log statements. The first will log the total number of books in the array, which I captured in a variable on the first line of the function. The second log statement will display the title of the first available book which I captured inside the for loop. Okay, we've now got a couple of functions and we need to write some code to call them. I want to get the array of books from the GetAllBooks function and then pass it to the LogFirstAvailable function. I'll use the const keyword to declare a new constant named allBooks, and assign it the value returned from GetAllBooks. I'll then just pass that constant to the LogFirstAvailable function. I'm going to close the sidebar just to make a little more room. Before we even try to run this, we can see that Visual Studio Code is letting us know we have a problem. We've got a red squiggly line under firstAvailable in the log statement. Nothing good ever came from a red squiggly line. I'll hover my mouse over it and we can see the pop-up message, Cannot find name 'firstAvailable'. Just to prove to you that this code won't actually compile, I'll open the Output window where the compiler is logging output, and you can see the same error was generated by the compiler, Cannot find name firstAvailable, on line 27 of app.ts. The reason it can't find that variable is because I declared it with the let keyword inside the for loop. The curly braces around the loop define the code block where that variable is available, but I'm trying to reference it outside that code block. I could make the error go away by declaring the variable with var instead of let. You can see that the red squiggly line went away. Although that makes the error go away, I think a better solution is to declare the variable with let in the outermost code block where it is needed, so I'm going to move it outside the for loop and change the var back to let. The red squiggly line didn't come back, so I think we're now ready to run the code and see the output. I'll close the Output window and open the Debug Console. I'll make it just a little smaller and then press F5 to launch the app in the debugger. We can see in the console that we have three total books, and the first one in the array that is available for checkout is Ulysses. Let's now turn out attention to the constant I declared to store the array of books returned from the GetAllBooks function. After declaring and initializing it, I'm going to add another line that sets it equal to an empty array. We immediately get a red squiggly line under it, and if I hover over it we can see that the left-hand side of assignment expression cannot be a constant. I'll quickly go back to the Output window, and we can see that the compiler generated the same error message. This all seems to make sense. You wouldn't expect to be able to change something that you've explicitly declared as a constant. However, let's change that line of code so that rather than setting the constant equal to a new array, I call the push function available on arrays and pass it an object literal that represents a new book. I don't get any red squiggly lines, and if I switch back to the Debug Console and run the app again, we can see that we now have four books in the array instead of the original three. The reason this worked is because the const keyword only guarantees that the identifier will not be changed to reference something entirely different. We can't change the allBooks constant to refer to an entirely different array, but we can change the data inside the array it already references. That's a subtle, but important, difference. Okay, I'll stop the debugger. I want to save that last book I added, so I'm going to move it up to the GetAllBooks function, and then delete the line of code that added it below. Let's now look through some of this code and examine the types being used. I didn't add any type annotations, so the types being used are those TypeScript was able to infer. I'll hover over the GetAllBooks function, and the signature shows that it returns an array of objects, and each object contains three properties named title, author, and available. TypeScript inferred, correctly, that the first two are strings and the last one is a Boolean. In later modules of this course, we'll see how to define and name our own types, but for now this will meet our needs. I'll move down to the LogFirstAvailable function. It takes a parameter, but TypeScript has no way to infer the type of that parameter so it currently has the any type. The compiler was able to infer that our function doesn't return a value, so the return type shown here is void. I'm going to make that explicit by adding a type annotation. After the parameter list I just add a colon followed by the void type. I generally prefer to use type annotations and be explicit about the types I'm using. I think it makes the code a little clearer for developers looking at it later and very clearly states your intentions for a variable or function, and removes the possibility that a bad line of code later will cause the compiler to infer a different, and incorrect, type. However, type annotations do make your code slightly more verbose, so you may decide that it's easier to read if you leave them off and let TypeScript infer many of the types. Okay, let's now move down to the NumberOfBooks variable. Because I'm assigning it a property of the books parameter, which is of type any, TypeScript can't infer the type of this variable either, so it's also any. I know it will be a number, so I'm going to add an annotation to it. I'll also add an annotation specifying that firstAvailable is a string. To again quickly demonstrate how TypeScript helps us catch bugs early, I'll now change this to try to assign it the number 42. We immediately see the error in the editor, which tells us we can't assign a number to a string. It's much better to find these problems now then when your code is running in a production environment. I'll change that back to an empty string to get rid of the error. Let's now go look more closely at enums and arrays.

  15. Enums, Arrays, and Tuples Enumerations exist in many languages and are usually just referred to as enums. They're used to give friendly names to a specific set of numeric values. You declare enums in TypeScript with the enum keyword. In this example I've declared an enum named Category which will be used to define different book categories. The friendly names for the enum values are placed inside the curly braces. Simply specifying the names, as I've done here, will assign the number 0 to the first name, 1 to the second, and so on. If you wanted the numbers assigned to the names to start with a different value, you can specifically assign a value to the first name, and the rest will increment from there. In this second example, I assigned the name Biography the value 1, so the values for Poetry and Fiction will be 2 and 3 respectively. You can also assign specific values to every name in the enum if you like. In this last example I've set Biography to 5, Poetry to 8, and Fiction to 9. You can declare that a variable will be of an enum type, just like you would any other type. Just add a colon after the variable name and then the name of the enum. Here I've declared favoriteCategory to be a Category enum, and then initialized it to be Biography by using the name of the enum followed by a dot and the name within the enum I want to use. If you print out the value of an enum, the value you see will be the number that the friendly name represents. Since my last example above set Biography to 5, that's what the log statement here would output. However, you can get a string representation of the friendly name by indexing into the enum itself with the value you want. Here I'm passing the favoriteCategory variable to the Category enum inside square brackets, and it will return the string, Biography. Arrays are a potentially big topic since they're one of the primary ways data is stored in JavaScript and TypeScript. The important thing to know when getting started with TypeScript is that arrays generally work the same way they do in JavaScript with a few notable exceptions we'll talk about now. The first is that arrays are usually declared to hold a single type, and there are two different ways to declare the same array. In this first example, I've declared a new array of strings. I've defined the type of the variable by specifying the type the array will hold followed by square brackets to denote that the variable will be an array of that type. I then initialize it with an array literal containing several strings. A second way you can declare an array of a particular type is shown here. This type annotation also specifies that the variable will be an array of strings, but it uses the generic syntax. We'll talk more about generics later in the course, but for now know that you can just use the Array keyword and then specify the type the array should hold inside the angle brackets right after it. Arrays in TypeScript are used very much like arrays in JavaScript. All the methods available on JavaScript arrays are also available on TypeScript arrays. If you do find yourself in a position where you need an array that can contain lots of different types like you might have used in JavaScript, you can get the same behavior in TypeScript by declaring the type that your array will contain as any. You can see in this example that I've initialized this array to contain a number, a Boolean, and a string. Tuples are a specialized type of array where you specify the type for the first few elements in the array. Those types don't have to be the same, and they're specified inside square brackets where you normally place type annotations. Here I've declared a tuple where the first element in the array will be a number, and the second element will be a string. If I then index into the array and retrieve the first and second elements, I will get the number 25 for element 0 and the string truck for element 1. You can add new elements to the tuple, as long as the types you store in those elements are one of the specific types you already declared. Because I declared the first two elements would be a number and a string, I can now put either a number or a string in the third element. Tuples are primarily used as a base from which you can declare new types. Let's now go use some of these new features in our demo app.

  16. Demo: Declaring Enums and Arrays In this demo I'm going to add some new code to the LibraryManager app to demonstrate using enums and declaring arrays. I'm in the same app.ts file from the earlier demo. I'll just scroll down a bit and then define a new enum to represent book categories. I'm not going to explicitly set the numbers that the names and the enums represent, so they'll just get the default values beginning at 0. Now that I've defined the enum, I want to edit the book object returned from the GetAllBooks function to include a new property that stores the books category. I'll call the new property Category and set it using the name of the enum followed by a dot and the category I want to assign. Notice the excellent code completion support I'm getting from Visual Studio Code for the enum I just created. Okay, now that every book has a category, I'm going to write a new function named GetBookTitlesByCategory. It will take a Category as a parameter. I'll name the parameter categoryFilter, and I'll add a type annotation so it can't accidentally be called with the wrong type. I want the function to return an array of book titles so I'm going to make that explicit as well and specify the return type to be an array of strings. Notice that this time I'm using the generic syntax with the type the array will contain inside angle brackets after the Array keyword. In the body of the function, I'm first going to log a message with the category passed to the function. I'll then call the GetAllBooks function that I wrote earlier and store the array of books in a constant called AllBooks. I need an array to store the titles of the books that match the category parameter, so I'll declare it here and initialize it to an empty array. It will be an array of strings, but notice that this time I declared it using the other array syntax. I first specify the type the array will contain and follow that with square brackets. I'm going to use a code snippet to paste in a for loop that will loop over the array of AllBooks, and compare their categories to the category passed to the function. If they match, I push the title of that book onto the filteredTitles array. I then just return the filteredTitles variable. I want to be able to print out the titles returned from the function, so I'm going to write a short helper function named LogBookTitles. Since the function I just wrote returns an array of strings, I'm going to specify an array of strings as a parameter for this function. It won't return anything, so I'll specify the return type as void. I'll write another for loop to loop over the titles in the string array and log them to the console. Okay, I now need some code to call these new functions. I'm going to delete these couple of lines we used in the last demo and declare a new constant to store the titles of the poetryBooks. I'll call the GetBookTitlesByCategory function and use the Category enum to retrieve just poetryBooks. I'll then call LogBookTitles and pass the poetryBooks constant to it. I'll press F5 to run it in the debugger. In the console we see that our library currently only has one poetry book. Above that we see the message, Getting books in category 1, since 1 is the enum value assigned to poetry. It would be more helpful if that showed the string representation of the category, so let's go fix that. I'll stop the debugger and close the sidebar. Okay, to print out the string representation of the category, I'm going to change the log statement to pass the categoryFilter as an index value to the category enum. That will return the string representation of that value. I'll run it again, and this time the message makes more sense, great. Now I want to quickly reinforce the value TypeScript provides in helping us write code with fewer errors. If I hover over the call to GetBookTitlesByCategory, we're reminded that it returns an array of strings. I'll do the same thing to the call to LogBookTitles, and we see that it should be passed an array of strings. I'll quickly change the parameter being passed to it to be an array literal containing numbers. I immediately get the dreaded red squiggly that tells me a number array is not assignable to a string array. It's all too easy to make these kind of mistakes in very large JavaScript applications, so it's nice that TypeScript all but eliminates that class of error for us. I'll change it back to the correct parameter so we can end this demo squiggle-free.

  17. Summary In this module we started exploring the TypeScript language, and how some of its fundamental constructs are different from the JavaScript code you've probably written in the past. Variables are important in every language, and as I said before, you can't have TypeScript without types, so we learned how to declare both. We wrapped up with a look at enums and arrays. You should now have a solid foundation on which you can build a thorough understanding of TypeScript. You can't write production-quality code without functions, so we'll explore them in the next module.

  18. Functions Introduction and Overview Hi. This is Brice Wilson. In this module we're going to cover TypeScript functions. Functions are obviously very important in just about every programming language. At first glance it may not look like TypeScript functions are very different from JavaScript functions, thankfully they are very similar, much like the rest of TypeScript, but there are some very nice additional features that TypeScript offers when working with functions to make your code more understandable and error free. I'll start this module by highlighting some of the similarities and differences between functions in TypeScript and JavaScript. Perhaps the most obvious difference is that TypeScript functions let you specify types for function parameters, as well as the value returned from the function. We'll see how to do that, and then dive into arrow functions, which provide a nice concise syntax when you just need an anonymous or simple callback function. The type system in TypeScript lets us use types for functions just like you use types for variables. We'll see how to define those types and declare function variables that use them. Parameters are one area where TypeScript adds lots of new functionality. I've already mentioned that you can specify types for function parameters, but you can also explicitly declare parameters as optional and assign them default values if you like. Rest parameters are a feature added to ECMAScript 2015 that TypeScript also adopted. They provide a mechanism for a function to accept a variable number of parameters that will be collected into an array. The final topic I'll cover in this module is function overloading. Many languages with strong type systems allow some form of function overloading, which lets you give similar functions the same name. There's lots to cover. Let's get started.

  19. Functions in TypeScript Versus JavaScript Let's start with a quick rundown of some of the differences between functions in TypeScript and functions in JavaScript. First up, types (of course!). Functions in TypeScript take advantage of the type system in TypeScript, which means we can declare types for our parameters and return values. JavaScript doesn't have types. TypeScript supports arrow functions, which we'll look at in just a minute. ES2015 added support for arrow functions, but they're not available in earlier versions of the language. TypeScript lets us define types for functions. Since it lacks types, we obviously can't do that in JavaScript. TypeScript supports required and optional parameters. This allows the compiler to make sure you're always using functions the way they were intended to be used. In JavaScript, all parameters are optional. This provides tremendous flexibility, but that flexibility can impair readability and safety. There's explicit support in TypeScript for specifying a default value for a parameter. There are some patterns that have evolved over the years to do this in JavaScript, but the syntax in TypeScript is much cleaner and easier to read in my opinion. This is another feature supported in ES2015, but not available in earlier versions of JavaScript. Rest parameters fall into that category as well. They're supported in TypeScript and ES2015 only. Finally, the types in TypeScript allow support for overloaded functions. Since there are no types in JavaScript, this is one of those features only available in TypeScript.

  20. Parameter Types and Return Types We saw in the last module how to specify types for function parameters, but I wanted to quickly review that syntax since we'll be looking at lots of function parameters in this module. Here I've got a very simple function named CreateCustomerID. It takes two parameters, name and id. I specify the types for those parameters by adding a colon after the parameter, and then adding the type of the parameter. In this example, the name parameter will accept a string, and id will be a number. I can additionally specify the type of the value that the function will return by adding a colon after the parameter list and then specifying the return type, a string in this case. With that quick review out of the way, let's take a look at arrow functions.

  21. Arrow Functions Arrow functions, sometimes called lambda functions, are a more concise way to write the anonymous functions that are used very often in JavaScript and TypeScript. In this example I've got a typical anonymous function. It's passed as a parameter to the filter function on an array. Even though the body of the function just contains one simple equality comparison, we still have to write an entire function which includes the function keyword, opening and closing curly braces around the function body, and the return keyword. That's a lot of extra stuff to have to read and write for one simple line of code. Here's the same code using an arrow function. The arrow that gives these functions their name is shown here. It's an equals symbol followed by the greater than symbol. To the left of the arrow are the parameters for the function. In this case, that's just the same book parameter used above in the anonymous function. To the right of the arrow is the body of the function, which is the same equality comparison from above. We don't have to use the function keyword, wrap the function in curly braces, or type the return keyword. The restful is a much more concise way to write the same code. If you've never used lambda functions in another language, then this syntax probably looks a little strange, and it may seem non-obvious what's going on. If that's the case, I just encourage you to give it some time. Experiment with writing some of your own. I think they'll quickly become very familiar. Just remember how to write the arrow, and that everything to the left of the arrow is a parameter and everything to the right is the function body. I'll show some more examples in just a second. A side benefit of using arrow functions is how they handle the often confusing "this" variable. "This" is normally set when a function is called, which can make it very confusing and hard to remember what it actually refers to. Arrow functions set the "this" variable when the function is created, not when it's invoked. We'll also look at that more in just a bit. Let's look a little more closely at the syntax for arrow functions. There are a few quirks to be aware of, and they're mostly related to defining the parameter list and function body. In this first example, I'm calling the forEach function on an array. It takes a function as a parameter, which will execute once for each item in the array. If my arrow function will not accept any parameters, I must add an empty set of parentheses where the parameters would have appeared to the left of the arrow. In this next example, I'm calling the same forEach function, but I'm now passing a single parameter to the Arrow function. This looks like the example from the last slide. Parentheses are not required if you're just passing one parameter. In the case when you want to pass multiple parameters to an arrow function, you're again required to wrap them in parentheses. So the rule is, parentheses are required around parameters unless you only have one. You can still place them around a single parameter if you like, but it's not required. All of these examples have a very simple one-line function body. You can include more than one line if you wrap them in curly braces. Here's an example that takes three parameters and has a body that would have several lines of code if I had more room on the slide. You can see that I wrapped the body of the arrow function in curly braces just like you're probably used to with anonymous functions in JavaScript.

  22. Handling 'this' in Arrow Functions Understanding the "this" variable in JavaScript is often quite confusing, and because it's set at the time a function is executed, it often represents two separate execution contexts in one conceptual block of code. In this example, I want to set a publishDate property on this object, and then refer to it inside a callback function passed to the setInterval function. This is a bit of a contrived example, but I hope it illustrates my point. I can't simply refer to publishDate as a property of "this", because "this" will refer to something different inside the callback. The pattern normally used to work around this in JavaScript is to capture "this" in a variable at the start of a function and then use the variable in the callback as I've done here. I assigned "this" to self, and then used self.publishDate everywhere. Arrow functions remove the headache of capturing the "this" variable and let you use it directly in a much more intuitive way. Here's the same code from the previous slide re-implemented with an arrow function for the callback passed to the setInterval function. Since the arrow function will capture the "this" variable for me, I can just set the publishDate property right on "this", and then refer to it the same way inside the callback function.

  23. Demo: Arrow Functions In this demo, I'm going to refactor some of my earlier code and write a new function to demonstrate using arrow functions. I'm going to start by adding a new property to each of the books in our very tiny library. I'll give each of them an id property, which will just be a unique number that will make it easier to find and work with books in our code. I now want to modify a bit of code I wrote in the last module to use an arrow function. I'm first going to just add a little comment separator between our growing number of functions and the code I'm writing to call them. I'll eventually start splitting the code across multiple files to keep it better organized. Okay, the code we've already got here gets a list of poetryBooks and calls the LogBookTitles function to print them to the console. Since our library currently has more fiction books, I'm going to change the name of the variable to fictionBooks and pass the Fiction category to GetBookTitlesByCategory. I'm not going to use the LogBookTitles function anymore, I'm going to replace it with a call to the forEach function available on the fictionBooks array, and I'm going to pass it an arrow function that will do the logging previously handled by LogBookTitles. All arrays have a function on them called forEach. it takes the function as a parameter, and that function takes three parameters. Remember that the parameters for an arrow function appear on the left side of the arrow, and if there are multiple parameters they must be surrounded with parentheses. In the case of the forEach callback function, val represents the current element in the array, idx, or index, represents the index of that value, and arr represents the array itself. The function body for our arrow function appears on the right side of the arrow, and it's just a single line. If it were multiple lines, I would have surrounded them with curly braces. I'm just logging the index position of the element and the value, which will be the title of the book. Note that I'm incrementing the index before I log it, just to account for the fact that arrays begin with index 0 and I want nice incremental output beginning with 1. Okay, I think you can see that this a much simpler syntax than if I implemented an anonymous function using the function keyword. I'll start the compiler build task and then press F5 to run the app. We get the expected output in the console window, perfect. I'll stop the debugger and go back to the code. I now want to write a new function named GetBookByID, which will make it easy for us to retrieve books using the new id property I created on them earlier. The function will take a number parameter that will be the ID of the book we want to retrieve. The first thing I'll do is get all of the books and store them in a constant. Because AllBooks is an array, it has a function on it named filter, which just returns a new array containing, presumably, a subset of the original. The filter function takes a function as a parameter. The function is passed each element in the array, and will return true or false to indicate whether the element should be included in the filtered output. Rather than passing an anonymous function to filter, I'm going to pass it an arrow function. I'll only pass it one parameter, so I don't need to wrap that parameter in parentheses like I would if there were 0 or more than one parameter. The body of the function on the right side of the arrow is just a simple Boolean comparison that checks to see if the ID of the current book matches the ID we're looking for. Since I intend to use unique IDs for my books, this function should never find more than one book, which means I can just return the first element in the filtered array. I know this isn't the most robust code in the world, but I want to keep it as simple as possible while still demonstrating the important points. Okay, so there's a second example of an arrow function. It's neat, easy to read, and fits nicely on one line. We've also now got a handy utility function we'll use later in the module. Before we do, though, let's talk about function types.

  24. Function Types In addition to defining types for function parameters and return values, functions as a whole have types. Function types are defined by the combination of the parameter types it accepts, and the type it returns. The PublicationMessage function shown here accepts a number parameter and returns a string. I can declare a variable that could hold a reference to this function much like I declare any other variable. I use the let keyword, and then place a colon after the variable name and follow that with the function type. The syntax for specifying a function type is to enclose the parameters and their types in parentheses on the left side of an arrow, and the return type of the function on the right side of the arrow. Don't confuse this with the arrow functions we just looked at. They look a little similar, but this is not an actual executable function, it's just a type definition for a function. Once I've declared a variable and given it that type, I can assign it the function above since that function shares the same type. If the type of the function I'm assigning doesn't match the type in the variable declaration, I'll get a compiler error from TypeScript. Once I've assigned the function to it, I can call the function using the name I gave the variable I declared. Let's take a closer look at function types in a demo.

  25. Demo: Defining and Using Function Types In this demo, I'm going to show you how to declare and use function types, and hopefully convince you that you can use them pretty much like any other type in TypeScript. I'm going to start by writing a very simple new function named CreateCustomerID. It takes two parameters, a string and a number, and just returns them concatenated together. Those types together define the type of the function, string and number parameters and a string return value. Let's now quickly call this function. I'm going to comment out this code we used in the last demo and just move it down some so it will still be available in the course download materials. Since the function returns a string, I'll just declare a new string named myID, and then call the function with the string "daniel" and the number 10. I'll then log the result. I'll press F5 to run it, and we can see that it output the concatenated string daniel10. I'll stop the debugger and go back to the code. I now want to demonstrate assigning this new function to a variable and using the variable to call it. In order to show that, it's really the same as any other variable declaration and assignment, I'm going to do it alongside about the simplest assignment you can make. Here's a new variable x and it's declared to be a number. It doesn't get much more basic than this, a variable name and a type. I'll now declare one that matches the type of our new function. I'll name the variable IdGenerator. I'll add a colon after the name, and then specify the type, just like I did for the variable x above. Function types are specified by listing the parameters and their types in parentheses followed by an arrow, and then the return type of the function. Notice that the names I specified for the parameters are different than those in the CreateCustomerID function. That doesn't affect the type. The function types are the same as long as the types of the parameters and the return type are the same. I can assign the number 5 to x because 5 has the type I declared for x. Similarly, I can assign the CreateCustomerID function to IdGenerator, because they each have the same type. I can now call the function using the IdGenerator variable. I'll change the number I'm passing to it, just so we can see that the output is a little different. I'll run it again. It still works as expected. This time we get daniel15 output to the console. The last thing I want to demonstrate is that the IdGenerator variable didn't have to be assigned a function previously written somewhere else in the code. I can directly assign it an inline function, as long as it matches the type I declared for the variable. I'll change the assignment to set the variable equal to an arrow function that matches the type I've already declared. In the body of the function, I'm still going to return a string, but I'll change it slightly this time and return the ID at the beginning instead of at the end. I'll also change the call to pass 20 this time. I'll run it one more time, and we still get the expected results. The important thing to remember is that function types are just like any other type. You can declare variables with them and assign functions to those variables if they have the same type.

  26. Optional and Default Parameters In JavaScript, all function parameters are optional. TypeScript is just the opposite. By default, all parameters are required, however, you can explicitly mark a parameter as optional if you like. In this first example, I've defined a function named CreateCustomer that takes two parameters, name and age. I can make the age parameter optional by adding a question mark after the parameter. That's the only syntax change required, although I will add that optional parameters must appear after all required parameters in the function definition. Default parameters let you specify a default value to be used for optional parameters or for required parameters when the caller passes undefined. Default parameters are treated as optional if they appear after all required parameters. You don't need to add the question mark after the parameter name. Here I'm assigning a default value to the title parameter. You set it with an equal symbol just like you assign a value to any variable. I've assigned a string literal here, but you can also use an expression in the assignment. Here the return value of the GetMostPopularBook function will be set as the default value for the title parameter.

  27. Rest Parameters Rest parameters give you a mechanism for passing a variable number of additional parameters after those specifically required in the function definition. You can think of them as the rest of the parameters the function expects. This function, named GetBooksReadForCust takes two parameters. I've defined the second parameter as a rest parameter so that I can pass a variable number of bookIDs as the list of books read by a particular customer. Those IDs will be captured in an array. In this case it will be a number array, but if you wanted the additional values to be strings or some other type, you could specify that here, however, the values will always be captured in an array of that type. A parameter is denoted as a rest parameter by placing an ellipsis in front of the parameter name. I can now call this function with any number of bookIDs. Here I am passing two IDs, but I could also call it it with more than that if I needed to. In this last example, the bookIDs array will contain the numbers 2, 5, 12, and 42. Let's go add some optional default and rest parameters to the demo app.

  28. Demo: Defining Parameters In this demo, I'm going to focus on different ways of declaring parameters. We'll look at examples of optional, default, and rest parameters. I'm going to begin by writing a new function named CreateCustomer that takes some optional parameters. Since we don't have a database, it won't actually create a customer anywhere, but we'll use it to log the values passed to it. It's going to take three parameters. The first will be the customer name, and will be required. The second will be age, and I'll make it optional by adding a question mark immediately after the name of the parameter. The third parameter will be city, and will also be optional. Remember that all optional parameters must appear after all required parameters, so I've added these after the required name. In the body of the function, I'm first going to log the name of the customer. I want to do the same thing for age and city, but since they're optional I'll use an if statement to see if they exist before logging them. I now want to call it with a few different parameter combinations. I'm going to comment out the code from the last demo and move it down a bit. I'll first call CreateCustomer with a single parameter, the required name. I'll run it, and we get just the one log statement with the new customer name. Since I didn't pass the other parameters, the if statements around them evaluated to false, and no attempt was made to log them. I'll call it again just passing the first and second parameters. This time there was a second parameter, so the if statement around it evaluated to true and it was logged. I'll do it one more time and pass all three parameters. As you probably expected, it logs all three values. Okay, let's now see how to use default parameters. In the last module, I wrote a function named GetBookTitlesByCategory that takes a category as a parameter and returns an array of string containing all of the book titles that belong to that category. If I try to call that function without a parameter, I get the red squiggly line letting me know something is not quite right. I'll hover over it, and it tells me that the supplied parameters do not match any signature of call target. We can also see the signature of the function, which clearly takes a category as a parameter. I'd like to be able to call this function without a parameter and have it use a default category in those cases. I'll scroll up to where I define that function. Adding a default value to the categoryFilter parameter is as easy as adding an equal sign and then the value that should be used if no value is passed to the function. I'll have it use the Fiction category. I'll come back down to the function call, and the red squiggly line has gone away. That's always good. Just to show that it can be used the way it was previously, I'll pass it the Poetry category and then log the title of all the books it returns. I'll run it, and it logs the one poetry book in our library. I'll now refactor the name of my variable to be fictionBooks, and move the parameter I'm passing to the function so that it uses the default value I specified earlier. I'll run it again, and this time we get all of the fiction books, since that was the default category I added to the function parameter. I also want to show you that you can set the default value of a parameter equal to an expression. It doesn't have to be a literal value. I'm going to make a call to the LogFirstAvailable function, which we also wrote in the last module. It currently expects to be passed an array of books and will print the title of the first book in the array that's available to be checked out. If I try to call it with no parameters, we get a red squiggly with the same message we saw earlier. I'll scroll up to the definition for the function and set the default value for the books parameters to be the array of books returned from the GetAllBooks function. I'll come back down, and we see that the red squiggly line is gone. I'll run the code, and it logs the first available book from the list of all books. Let's now write a function that accepts a rest parameter and see how they work. I'll start by writing a new function named CheckoutBooks. I want to be able to pass this function a customer name and a list of the book IDs he or she wants to check out. It might be 1 or it might be 10. The first parameter will be a string for the customer's name. The second parameter will be a rest parameter that will capture all of the bookIDs. I'll name the parameter bookIDs and denote it as a rest parameter by placing an ellipsis, three dots, in front of the parameter name. Since each bookID will be a number, the type of the rest parameter will be an array of numbers. All of the IDs I pass will be captured in a single array. The function will return an array of strings that will contain the titles of all the books that were checked out. I'm going to use a code snippet to paste in the body of the function. The function first logs the name of the customer. I then declare a new string array to store the book titles for the books that are actually checked out. The bookID's rest parameter captures all of the IDs in an array, which I can loop over just like any other array. I loop over all of the IDs and use the GetBookById function we wrote earlier to retrieve each book and check its available property to see if it can be checked out. If so, I push the title of the book onto the booksCheckedOut array. After looping over all the IDs, I return the array of titles. The important pieces to note here are the syntax for declaring a rest parameter with the ellipses, with the fact that once the values are captured in an array I can use it like any other array inside the function body. Let's now see how to call the new function. I'll declare a new string array named myBooks to store the titles returned from the function. I'll first call it with a customer name and one bookID. As I've done before, I'll call forEach on the returned array and log the results with an arrow function. I'll press F5 to run it. It logged the customer name and the name of the book he checked out. I'll change the code to pass three bookIDs this time. I'll run it again, and as expected, three books are logged. I hope you've seen that optional default and rest parameters are very nice features that allow you to maintain the flexibility you may have enjoyed with JavaScript, but also add some checks along the way that will improve the quality of your code.

  29. Function Overloads Function overloading is a feature that exists in many typed programming languages. If you're not familiar with the concept, it basically means that you create multiple functions that have the same name, but differ in their type somehow. The concept is the same in TypeScript, but the implementation is a little different since TypeScript compiles to JavaScript, which does not have types. Because the types are removed at compile time, having multiple JavaScript functions with the same name will cause a problem. Therefore, in order to overload functions in TypeScript you provide multiple function definitions, but you only provide one implementation. That implementation function must use type guards to determine which overload was called and what action to perform based on that. In this example, I'm going to overload a function named GetTitles. The first version of this function will accept a single string parameter and return an array of strings. The second version will accept a boolean parameter and return an array of strings. Notice that neither of these functions contains an implementation. I've basically told TypeScript that I want to have two versions of the GetTitles function that will differ in the type of parameters they accept. I now need to provide the implementation function. Since there will only be one actual implementation, but it needs to work with both string and boolean parameters, I'm going to declare the type of the parameter on the implementation to be any. Then, inside the function I have to check the type of the parameter and execute different conditional logic based on that. I first check to see if the parameter is a string, in which case I would go gather a list of books by the author name in the string. If the parameter is a boolean, I gather books based on their availability, true or false. This is admittedly a little clunky, but it does provide you with a way to overload functions, which is supported by some editors like Visual Studio Code, as we'll see in the next demo.

  30. Demo: Using Function Overloads In this demo, we're going to see how to overload functions and the tooling support for them provided by Visual Studio Code. If I were actually running a library, I imagine one of the things I might want to be able to do is to gather a list of bookTitles based on different criteria. In this demo I'm going to build an overloaded function named getTitles that lets me retrieve an array of titles, either by author name or based on whether or not the book is already checked out. To create an overloaded function, I first need to define the signature for each of the overloads. The first one I'm going to define will take a string as a parameter, and will be the name of the author whose books I want to retrieve. The function will return an array of strings, so I'll add that to the signature as well. The second overload will take a Boolean parameter and will represent whether we want to retrieve books currently available or those already checked out. I'm now going to write the implementation function. I'm going to declare its parameter with the any type, since it needs to be able to accept either strings or booleans, and I'm going to give it the very generic name bookProperty. I'll create a constant to store all of the books in the library, and then another one that will store the array of titles matching the criteria passed to the function. I'll use a code snippet to paste in a chunk of code that will handle the case when we pass a string parameter. The code checks the type of the bookPropery parameter. If it's a string, then it loops over all of the books, looking for those whose author matches the string passed to the function. When it finds a match, it adds the title to the foundTitles array. I'll use another snippet for the code that will handle boolean parameters. This code is very similar to the first block. It also checks the type of the function parameter. If it's a boolean, it loops over the books checking to see if the available property matches the value passed to the function. Passing true to the function will returned books that are available, and passing false will return those already checked out. At the end of the function, I just return the foundTitles array. Let's now declare a new variable named hermansBooks, and assign it the array returned from the function. Notice that once I type the parentheses on the function, Visual Studio Code knows that there are two overloads for this function, and shows them to us in the little code completion pop-up. You can see that this is version 1 of 2, and it takes a string as a parameter. I'll hit the down arrow on my keyboard, and it tells us the next one is version 2 of 2, and that it takes a boolean parameter. I'm first going to call the string version and pass it 'Herman Melville'. I'll then use the arrow function I'm so fond of to log the result. I'll hit F5 to run it, and it correctly logs Moby Dick to the console. I'm now going to refactor the variable name to be CheckedOutBooks, and I'm going to pass false to the GetTitles function. There are no red squiggly lines, so we know this is a perfectly valid way to call the function. I'll run it again, and we can see that a Farewell to Arms is the only book currently checked out.

  31. Summary Functions are just as important in TypeScript as they are in JavaScript, and I hope you've seen in this module that TypeScript functions are just like JavaScript functions, but with more features to help you write better code. We saw how to make your code more concise and readable with arrow functions, and how they remove the headaches that often accompany capturing the "this" variable. Types are obviously important in TypeScript, and we saw that they even apply to functions as a whole, and how you can declare variables of a particular function type and then call a function using the variable. Optional and default parameters are my favorite function-related features in TypeScript. They're simple, but I really think they make your code more readable and make sure the callers of your functions use them as you intended. Finally, we saw how to overload functions in TypeScript. The implementation syntax for overloads may feel less than ideal if you're used to other languages like C# or Java, but it's still a niece feature to take advantage of if you're, perhaps, writing an API and want to provide your callers multiple ways to retrieve the same type of data. In the next module, we'll finally begin defining our own types with interfaces. They are definitely one of the best features of the language. Stay tuned.

  32. Interfaces Introduction and Overview Hello. Welcome back. This module will be all about interfaces. Interfaces play an important role in TypeScript by giving us a means to define our own types, types that the TypeScript compiler can then check for us and make sure we're using correctly. I'll begin this module by defining exactly what an interface is, and the reasons why we need them. That will lead us into a brief discussion of duck typing and how it applies to TypeScript. We'll then get to the actual syntax for declaring interfaces, both for general types, as well as function types. Interfaces can also be extended and composed from other interfaces, and we'll see how to do that as well. I'll wrap up this module with a brief look at classes and how you can use them to implement an interface.

  33. What s an Interface? So what is an interface? An interface is like a contract. It's a contract that defines a type. The compiler enforces the contract via type checking. This amounts to generating errors if some bit of code references a property or method not defined on the type, or perhaps tries to use the type without all of the required properties and methods. In both cases, the interface is the contract that defines how a type can and cannot be used. Because interfaces define custom types, and JavaScript doesn't support custom types, interfaces don't compile to anything in JavaScript. They're just used by the compiler for type checking. An interface is said to specify the shape of an object. It's a collection of property and method definitions, but it provides no implementation details. What this means is that an interface may specify that a type should have a method named GetBook, for instance, and it may specify that the method should accept one parameter that's a number, however, it won't specify the body of the method or what should actually happen when the method is called. Those implementation details are provide by a class or object that implements the interface. An interface is a contract without the implementation details, similar to signing a contract to rent a new apartment. That contract will specify that you pay a precise amount of money each month for the apartment, but it won't specify how should you go about earning the money you'll use to pay for it. That's an implementation detail that could be different for each person. Because TypeScript interfaces focus on the shape of an object, they're a form of duck typing. What this means is that as long as an object has the shape of an expected type, then it can be used as if it were that type even if it was not explicitly declared to be so. It's important to understand the concept of duck typing in order to fully grasp how interfaces in TypeScript work, so let's take a closer look at it now.

  34. Duck Typing The idea behind duck typing is based on the so called duck test. The original source of the duck test is debatable, but it's often traced to this quote from the American poet, James Whitcomb Riley, "When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck," the idea being that a thing needn't have a label on it to be recognized and treated as the thing it most resembles. This idea has been incorporated into the vocabulary of type systems when objects that possess the shape of a known type are allowed to be treated as that type, even if they haven't explicitly been declared as that type. Let's look at a very literal example of an actually duck type. In this example, I've created a new interface named Duck. The interface specifies a list of functions that all ducks can perform. They can walk, swim, and quack. In this next bit of code, I've declared a new variable named probablyADuck, but I haven't specified that it will be of a particular type. However, it's an object that has methods named walk, swim, and quack, and the signatures for those methods exactly match those on the Duck interface. Next I'm going to define a new function named FlyOverWater that takes a Duck as a parameter. Since the object I declared has all the methods required on the Duck interface, I can pass it to the FlyOverWater function even though I didn't declare it as a Duck. My object walks like a duck, swims like a duck, and quacks like a duck, so I can call it a duck and use it where a type of duck is expected. That's duck typing, quite literally in this case.

  35. Defining an Interface Let's now look at the syntax for defining an interface. It starts with the "interface" keyword followed by the name you want to give the interface. The definition of the interface will be placed inside curly braces. You specify properties by naming the property and then specifying its type after a colon. Here I've specified properties named id, title, and author. All of these properties are required for any object that implements this interface, however it is possible to specify optional properties. The syntax is the same as that used for optional parameters for functions, you just add a question mark right after the property name. Methods or functions can be specified on an interface by giving the method a name and a signature. My Book interface will have a method named markDamaged that will take a single string parameter and return void. In the next two clips, I'm going to restructure the demo app into multiple files and then add a book interface to the library manager app.

  36. Demo: Restructuring the LibraryManager App Before I define my first interface, I'm going to take just a couple of minutes in this demo to start splitting the code in the LibraryManager project into multiple files known as modules, which I think will make it more readable and understandable throughout the remainder of the course. I'm going to cover modules in lots more detail in a later course module, so this will just be a very brief preview of things to come. In order to use modules, I need to tell the TypeScript compiler what module format it should use when compiling our code to JavaScript. I've specified the compiler options I'm using on the build task defined in the tasks.json file. I'll open that file from the .vs code folder. The compiler options are stored in the "args" array. I'm going to add a new one named --module. There are several module formats the compiler recognizes, and I'll discuss them all later in the course, but for right now I'm going to use the "commonjs" format popular with Node.js developers. Okay, now that the compiler knows how to handle our modules, I can begin adding new code files to the project and treating them each as their own module. For the sake of simplicity, I'm going to keep all of my enums, interfaces, and classes in separate files. I'll go back to app.ts and cut out the Category enum we already have. This will obviously break some things, but I'll come back and fix them once we have our new modules in place. I'll create a new file in the project named enums.ts and paste the Category enum in it. When working with modules, we have to export from each module the things we want to be accessible to other modules. We use the export keyword to export them, and then we use the import keyword to use them inside another module. To export the Category enum, I'll just type export followed by the name of the enum, Category, inside curly braces. You'll notice that after typing that line I get a red squiggly line under it. I'll hover over the line and the error message tells me that I cannot compile modules unless the '--module' flag is provided. I just added the module compiler flag inside the task.json file, Visual Studio Code just isn't recognizing that yet. This is one of the early quirks with Visual Studio Code. Now that I have a new module for enums, I want to create a new module for interfaces. I'll add another new file named interfaces.ts. I want to have access to the Category enum so I can use it on the interfaces I'm going to create. To make it available, I'll import it at the top of this file. I just use the import keyword followed by the thing I want to import inside curly braces. I then specify where TypeScript can find the thing I'm importing. I use the word from and then provide a relative path to the file that contains the Category enum, but I leave the ts extension off of the path. Again, don't worry too much about the export and import syntax right now, I'll show you a lot more about them later. Okay, we're finally ready to define our first interface.

  37. Demo: Defining and Using Interfaces In this demo we're going to see how to define and use a basic interface in TypeScript. We've already seen a need for a Book type in our app, so that's where we'll start. I'll use the interface keyword and create an interface named Book. I'll use a code snippet to paste in some properties on it. Right now I'm just giving it the same properties I defined on the object literals I've used so far in the course. Notice that the category property is of type Category, which is only available here because I imported it at the top of the file. Now that we have a simple book interface, let's update our code inside app.ts to use it. To make it accessible in other modules, I need to export it from this one just like I exported the Category enum. I'll now go back to app.ts. I'll close the sidebar to give myself a little more room, and then jump up to the top of the file. To fix the problems I created when I removed the Category enum from this file, as well as to make the new Book interface available, I'm going to import each of them. The import statement for the enum will be identical to the one I used to make it accessible inside the interfaces file. The import statement for the Book interface will be similar. I'm importing Book, and the relative path will just be ./interfaces with no file extension. The first place I want to use the new Book interface is on the GetAllBooks function here at the top of the file. We know it's meant to return books, but until now we haven't had a book type. To highlight the value of explicitly returning a type, I'm going to remove the id property from the first object in the array currently being returned. You can see that when I remove that we don't see any new errors in the editor. As far as TypeScript is concerned, we're currently just returning an array of objects. They are currently of type any, which means every one of them could have different properties. I'll put the id property back, and now I'll give the function an explicit return type. I'll use the new interface and specify that it should return an array of books. If I again remove the id property from the first item in the array, we now get an error trying to return the array from the function. I'll hover over the variable with the error. Visual Studio Code is cutting off the error a little bit at the top of my screen, but it says that property id is missing in type. Since I've explicitly declared that the function should return an array of books, every item in the array must implement the Book interface, which means each object must contain all of the properties declared on the interface. I'll get rid of the error by putting the id property back on the first object. I'll scroll down a bit and again use the Book interface as a function return type. The GetBookByID function will return a single book. Specifying types like this will make sure we use these functions as they were intended to be used. I now want to add a new function, so I'll scroll down a little further to the end of the file. I'm going to name the new function PrintBook. It will take a single parameter named book that will be of type Book. It won't return a value, and will just log the title and author of the book that is passed. Because I've specified a type for the parameter, you can see that I'm getting code completion help inside the function when I use that parameter. Visual Studio Code recognizes all the properties available on the Book interface. I'm now going to write some code to call the new function. I'll first declare a new variable named myBook. It will just be an object literal. I'll use a code snippet to paste in some properties for it. Notice that I haven't declared that this variable is of type Book, but it has all of the properties defend on the Book type, id, title, author, available, and category. It also has a couple of additional properties, year and copies. I'm going to pass this object to the new PrintBook function. Notice that I don't get any error messages in the editor. This is an example of TypeScript's duck typing. Even though I didn't explicitly declare that the myBook variable was of type Book, it has all of the properties defined on a book, which means I can use it anywhere a book is expected. That's true even though it has a couple of additional properties. I'll run the build task to start the compiler and then press F5 to run the code. We can see that the object was treated as if it had been declared as a book, and we get the expected output in the console. That's duck typing in action. I'll stop the debugger and close the sidebar. I now want to demonstrate optional properties on an interface. I'm going to open the interfaces file in the left editor and app.ts in the right editor, so we can immediately see the effect my changes have on the code that uses the Book interface. The first change I'm going to make is to add a new property to the interface, named pages. It'll be a number. Notice that as soon as I add it I get an error trying to pass the myBook variable to the PrintBook function. PrintBook expects an object that implements the Book interface, which now has a property named pages. The myBook variable doesn't have that property. I'll hover over it, and buried in the error message is a bit of text telling us that Property 'pages' is missing in type. If we want the myBook variable to be treated like a book, it must have all of the required properties defined on a book. I'll change the pages property to be optional by adding a question mark after the property name. Since the property is now no longer required, the red squiggly line under the myBook variable immediately goes away. Let's now see what happens if I explicitly declare the myBook variable to be of type Book. When you constrain a variable to be of a particular type, it's no longer permissible to include extra properties that are not defined on the type. Because the Book interface doesn't have a year property, I'm getting an error trying to add it here. I'll delete it, and now I get an error on the copies properties, which is also not part of the Book interface. I'll go ahead and delete it as well, and now the compiler is happy again. I'll add the new pages property to this object, and you can see there are no issues with it. Interfaces can also contain method signatures, so let's now add one of them to the Book interface. I'm going to add a new method named markDamaged. I'll add a question mark after the name to make it optional, and then I'll provide the function signature. It will take a string parameters named reason, and won't return a value. Even though it's optional, I'm going to provide an implementation for it on the myBook variable. I'll assign it an arrow function that just logs the word 'Damaged' followed by the reason passed to the function. I'll then call the function on the object and pass it the string, 'missing back cover'. I'll run the app again, and you can see I did properly implement the method defined on the interface. The expected output shows up in the console. Let's now talk about defining interfaces for function types.

  38. Function Types In the last module, I talked about functions and I showed you that functions have types defined by their parameters and return values. I also showed you how you can declare a new variable that has a particular function type, and that you can assign functions to the variable. We can use interfaces to give those function types names. This makes our code more readable, and makes the types we declare more reusable. Here's the function I used to demonstrate the concept of function types in the last module. The CreateCustomerID function takes string and number parameters and returns a string. I then declared a new variable named IdGenerator, and declared it to have a function type that matches the signature of CreateCustomerID. I was then able to assign CreateCustomerID to the IdGenerator variable. That all works fine, but if I wanted to use it in multiple places it would be better to have the type defined in a single place. To do that, I'll create a new interface named StringGenerator. It just gives a reusable name to the function type that has the signature we're using, string and number parameters and a string return type. Notice that the function signature is specified inside curly braces like other interfaces, but the syntax is slightly different from the function type declaration I made for the IdGenerator variable. Here I use a colon between the parameter list and the function return type instead of the arrow symbol. Now that I have an interface that defines the function type I need, I can change the IdGenerator declaration to use it instead. I think this is much easier to read. IdGenerator is of type StringGenerator. I can also now use StringGenerator in other places when I need similar functionality. Let's go add an interface for a function type to the demo app.

  39. Demo: Interfaces for Function Types In this demo I'm going to define a new function interface and modify the Book interface to use it. In the last demo, I added a function to the Book interface named markDamaged. I now want to create an interface for the function and use that instead. I'll add the new interface to the interfaces.ts file and name it DamageLogger. It just needs to define the signature of the function, which will accept a string parameter and return void. Remember that when defining a function interface you specify the return type by placing a colon rather than an arrow after the parameter list. That's all there is to it. I can now change the type of the markDamaged function on the Book interface to be of type DamageLogger. I'm also now free to export this interface and use it completely independent of the Book interface. To do that I'll just add it to the list of exports from this module. I'll go back to app.ts and jump to the top of the file and import the new interface. Since it's exported from the same module as the Book interface, I can just add it as another import in the list right after book. I'll jump down to the end of the file so we can test the changes. Since the DamageLogger interface defines the same signature on the Book interface, the implementation currently on the myBook variable should still work. Just to prove that, I'm going to modify the reason for the damage and run the code again. The new reason is correctly displayed in the console. I now want to write a quick example that uses the DamageLogger interface independent of the Book interface. I'm going to comment out these couple of lines of code. I'll declare a new variable named logDamage that is of type DamageLogger. TypeScript now knows that the variable will contain a function, and it knows the signature the function must have, but not the implementation, I have to provide that. I'm going to assign it an arrow function that is just slightly different from the implementation I used on the myBook variable. It will log the string 'Damage reported', followed by the reason passed to the function. I then use the variable to invoke the function by passing a string parameter inside parentheses like any other function call. I'll run the code, and we again see the expected output in the console. Let's now see how to extend smaller interfaces and compose them into larger interfaces.

  40. Extending Interfaces Interfaces can be extended and composed from other interfaces to make new types that contain all of the properties and methods of their composite types. Let's walk through a very simple example. Here I've defined a new interface named LibraryResource that has one property named catalogNumber. I'll define a second interface named Book that has one property named title. Lastly, I'll define a third interface that extends the first two. This interface is named Encyclopedia, and I want it to have all of the properties defined on the previous interfaces, as well as a new property of its own. To make that happen, I use the extends keyword followed by a comma-separated list of the interfaces I want to extend, LibraryResource and Book. If I now declare a new variable and give it the type Encyclopedia, it will have all three properties, catalogNumber, title, and the volume property explicitly declared on Encyclopedia. Let's add a slightly more involved example to the demo app.

  41. Demo: Extending Interfaces In this demo, I'll create new interfaces and show how they can be extended and composed into other interfaces. I'll start in the interface.ts file and create a new interface named Person. I'll give it two properties, name and email, both will be strings. Next I'll create an interface named Author that extends the Person interface. As we saw in the slides, extending an interface is very simple. You just add the extends keyword followed by a comma-separated list of the interfaces you want to extend. I'm only extending one in this example. The extension to Person will consist of a single property named numBooksPublished, and it will be a number. I'm also going to create another interface that extends Person. This one will be named Librarian, and we'll add a string property named department and a method named assistCustomer. The method will take the name of the customer to be assisted as a string, and return void. Before we can go experiment with the new interfaces, I need to export them from the module. I'll then jump back over to the app.ts file and add them to the list of imports from the interfaces module. I'll jump back to the bottom of this file where I've been writing my test code. I want to demonstrate that the author and librarian interfaces do, in fact, have their own properties, as well as those inherited from the Person interface. I'll declare a new variable named favoriteAuthor and declare it to be of type Author. I'll then start to set it equal to an object literal. I'll press Ctrl plus the space bar in Visual Studio Code, and it shows me a list of the properties available for me to add to an object of type Author. If you look closely, you can see that it gets the email property from Person, name is also from Person, and numBooksPublished is defined on Author. I'll now do the same thing for the Librarian interface. I'll declare a new favoriteLibrarian variable of type Librarian. I'll press Ctrl space inside the object literal, and we can see the four available properties. assistCustomer is the function defined on Librarian, department also comes from Librarian, and name and email are defined on Person. We'll use those interfaces some more in a bit. I'm going to delete these lines for now and move to a discussion of class types.

  42. Class Types Classes are a big topic in TypeScript, and I'll cover them in detail in the next module of the course, however, I want to give you a quick peek at them now and show you how they can work in conjunction with interfaces to easily define and create objects you can work with. remember that interfaces only define the shape of an object. They don't provide a mechanism for actually creating an object, or defining the implementation details for the properties and methods on it. So far in this module, I've been creating objects that implement my interfaces by defining object literals inside curly braces. Classes give us a much nicer way to do this. I'll start with a simple interface named Librarian that just has a single method named doWork. It doesn't take any parameters and doesn't return a value. I'll then use the class keyword to create a new class named ElementarySchoolLibrarian. After the class name, I use the implements keyword to specify that the class will provide the implementation details for the Librarian interface. Inside the class, I've defined the doWork function I'm required to implement. Since this implementation of the interface is for an elementary school librarian, doing work means reading to and teaching children, but there could be other librarian classes that implement doWork quite differently. To create an actual ElementarySchoolLibrarian object I can work with, I'll declare a new variable and give it the type Librarian, which means the object I assign to it must implement the Librarian interface. I'll create an ElementarySchoolLibrarian object using the new keyword followed by the class name and a pair of parentheses. This is calling the constructor function with the class with no parameters. We'll talk more about constructor functions in the next module, but right now just know that the constructor returns a new object and assigns it to the kidsLibrarian variable. I can then call methods on the object and use it like I did the object literals I declared earlier. Let's now add a class that implements an interface to the demo app.

  43. Demo: Implementing Interfaces with Classes In this demo, we'll see how to create classes that implement interfaces. I'll start by creating a new file to hold our classes. I'll name it classes.ts. The first thing I'll do is import the interfaces I've created. Even though I don't need them all right now, I'll import Book, DamageLogger, Author, and Librarian. I'll now create a new class named UniversityLibrarian, that implements the Librarian interface. Implementing the interface means providing code for all of the required properties and methods on the interface. I'll use a code snippet to paste in the implementation. It includes everything required on the Librarian interface, the name and email properties inherited from the Person interface, as well as the department property and the assistCustomer method from the Librarian interface. Implementing the properties can be as simple as defining them, as I've done here. The simple assistCustomer implementation just logs a simple message using the name of the librarian and the name of the customer he or she is helping. To make this class available to other modules in the app, I need to export it the same way I exported the interfaces from the interfaces.ts file. I'll now open the app.ts file and jump up to the top of it. I need to import the new class so I can use it here. The import statement will look very much like the other two I already have in this file. With that in place, I'll jump back to the end where I write my test code. I'm going to declare a new variable named favoriteLibrarian, and specify that it will be of type Librarian. I'll then set it equal to a new instance of UniversityLibrarian. Because the UniversityLibrarian class implements the Librarian interface, I can assign UniversityLibrarian objects to any variable or parameter expecting a Librarian. Next I'll just set the name of my favoriteLibrarian, and then call the assistCustomer method and pass the name of a customer. Unlike the object literal I created in the earlier demos of this module, I don't have to provide an implementation for methods here in the object declaration. Implementations are stored in the classes themselves, and I can simply invoke them after creating an instance of the class. I'll go ahead and run this code just to make sure it works as expected, and it does. We can see the message output by the assistCustomer method in the console. I'll stop the debugger and close the console. The last thing I want to show you before wrapping up these interface demos is the result of compiling our new interfaces.ts file. I'll open the file, and you can see that we're already up to five interfaces, the Book interface, the DamageLogger function interface, and then the Person, Author, and Librarian interfaces. Let's now go into the js folder in the project and look at the interfaces.js file that the TypeScript compiler produced. There's nothing in it, nothing but a reference to the source map file. That's because interfaces don't have an equivalent construct in JavaScript. They don't contain implementation details, and don't represent or create actual objects, they're just a means for us developers to define the contracts between the various parts of our application, and for the compiler to enforce type checking.

  44. Summary In this module, we covered interfaces and the important role they play in type checking. I also explained duck typing and how it applies to TypeScript. We then got into the details and saw how to declare, use, and even extend interfaces. We then saw how to implement interfaces with classes. That was an important interface topic, but also gave you a preview of classes and a nice segue into the next module of the course, which is all about classes. They provide a great way to organize and encapsulate functionality, and provide a formal syntax for a pattern JavaScript developers have struggled to implement for years. Keep watching to learn more.

  45. Classes Introduction and Overview Hi, this is Brice Wilson. Welcome back. In this module I'm going to cover TypeScript classes. Classes are a very natural extension to interfaces and implement a pattern JavaScript developers have hacked together in lots of different ways over the years. I'll start this module by explaining what classes are and the role they play in TypeScript development. Since classes should be a familiar concept to object-oriented developers, I'll briefly describe how TypeScript classes are similar to classes in other popular languages. I'll discuss the different types of class members, constructors, properties, and methods, and then discuss the concept of inheritance and how we can extend TypeScript classes into new classes. I'll wrap up with a look at abstract classes and class expressions.

  46. What Is a Class? Before I get too deep into the details, let's define what a class is. In very general terms, a class is a template for creating objects. All of the objects created from the template will have the same properties and methods. Classes also provide state storage and behavior. They define properties which can store data in the objects created from the class, and they provide behavior in the form of methods defined on the class. Perhaps most importantly, classes encapsulate reusable functionality related to a particular entity. I'm using the term entity very generally to mean some thing. That thing might be a book or an author in our Library app, or it could be a team or a player in a sports app of some kind. Classes help us think about our programs in simpler terms that have some direct relation to our problem domain. If you've ever done any development in an object-oriented language like C# or Java, then a lot of what I'm going to cover in this module should sound very familiar, and I imagine you'll feel right at home. Much like those languages, TypeScript classes define types and contain properties and methods. They also have constructors and access modifiers you can apply, and they support inheritance and abstract classes. All of the functioning programming goodness of JavaScript remains, but TypeScript adds to that the object-oriented constructs familiar to many developers. The first of these we'll look at is constructors.

  47. Constructors Constructors are functions that perform initialization for new instances of a class. In this example, I've used the class keyword to define a new class named ReferenceItem. A class's constructor looks like any other method, except that it's named constructor. In TypeScript there can only be one constructor function per class. Some object-oriented languages allow you to create multiple constructors that differ by the number of parameters they accept. You can achieve similar goals in TypeScript through the use of optional parameters. This constructor takes two string parameters, title and publisher, however, notice that I've used the question mark after the publisher parameter to denote that it's optional. This allows our single constructor function to accept a variable number of parameters should we decide we need to support that functionality. Classes are used to create new objects known as instances of the class. In this example, I'm creating a new instance of the ReferenceItem class, and assigning it to the encyclopedia variable. You create a new instance using the new keyword followed by the name of the class and any parameters expected by the constructor. Notice that you don't execute the constructor by calling it by name, you use the class name and the "new" keyword, however, this will execute the constructor function and return a new instance of the class.

  48. Properties and Methods Like interfaces, classes can contain properties and methods, but unlike interfaces, classes provide the actual implementation details. Here I've got the shell of a ReferenceItem class. There are a couple of different ways to define properties on a class. The first is just to define a new variable inside the class. This property is named numberOfPages. It's a number, and I can get or set its value on an instance object just using the normal dot syntax we've already seen. The second way to define properties is to create custom accessors. Accessors are getter and setter functions that give you more control over how property values are set and retrieved. They have their own special syntax. In this example, I'm creating accessors for a new property named editor. You define them by using the get and set keywords. Accessors are basically just functions, but they both have the same name. Since my property will be named editor, that's the name I use for both accessors. The getter will always contain an empty set of parentheses after the name. You can optionally set a return type as I did for mine. The setter must be passed exactly one parameter, and you are not allowed to specify a return type for it. Inside the bodies of the accessors, you can perform any special logic you need for the property. Consumers of the class will access the property with the dot syntax just like any other one. Methods are pretty straightforward. They're just functions defined inside the class. Here I've got a method named printChapterTitle that takes one number parameter, and doesn't return a value. You also call methods on a class using the dot syntax we've seen many times already. It's very common to initialize properties on a new object by passing parameters to the class's constructor, and then setting the properties equal to the parameters inside the constructor. Parameter properties are a shortcut for that common pattern. In this simple class, I have a name property. The constructor takes a single parameter which is then assigned to the property. I accomplish the same thing in this second example with much less code. I don't explicitly declare a new property, instead, I place the public keyword in front of the constructor's parameter name. That tells the TypeScript compiler I want a property with the same name as the parameter, and that it should be set equal to the value passed to the constructor. It's a nice shortcut that eliminates the explicit property declaration and the assignment inside the constructor body. Static properties are properties of the class itself, not of the class instances like the properties we've seen so far. In this Library class I've defined two properties. The first is a parameter property named name, which will be available in all instances of the class. Each instance can set the property equal to whatever value is appropriate for that instance. The second property is named description, and I've prefixed it with the static keyword. It will, therefore, only be available on the class, and not on instances of the class. If I declare a new instance of the Library class and assign it to a variable named lib, I can then reference the name property on that instance. However, if I want to reference the description property, I must reference the Library class itself. Static properties give you a place to store data specific to the class that doesn't vary across instances of the class.

  49. Access Modifiers Access modifiers are keywords that can be added to property and method definitions to control their visibility for consumers of the class. By default, all class members are public. This is an important point, especially if you have a Java or C# background, because public is not the default in those languages. You can explicitly add the word public in front of TypeScript properties and methods if you like, but it's not required. But one exception to that is in the case of the parameter properties, which we saw a couple of slides back. The public keyword is required to declare a constructor parameter as a class property. You can use the private modifier to declare that a class member should only be accessible inside that class. Members declared private will not be accessible to consumers of the class, or in subclasses, which we'll look at shortly. Members declared as protected are only available inside the class in which they are declared, or any subclasses of that class. They're not publicly available on instance objects. Let's go see classes in action in a demo.

  50. Demo - Creating and Using Classes In this demo, I'll show you how to create a new class, and how to use constructors, properties, methods, and accessors. I'm going to start this demo in the classes.ts file I created in the last module on interfaces. I gave you a brief preview of classes when I built this UniversityLibrarian class that implements the Librarian interface. I'm going to begin here by adding a new class to the file named ReferenceItem. I'll give it two properties, title and year, to represent the year it was published. I'll also add a constructor to the class. Remember that constructors in TypeScript are actually named constructor. I won't include any parameters yet, and in the body I'll just log that a new ReferenceItem instance is being created, so that we can observe when the constructor is actually being called. I've got properties and a constructor, so for the sake of completeness, I'll also add a method. I'll name it printItem and keep it very simple, no parameters, and no return value. It will just log some information about the ReferenceItem. Since I'm obviously a fan of the humble console.log function, I think it's time I show off a feature added to ECMAScript 2015 that's also supported in TypeScript. They're called template strings, and they allow you to embed expressions in string literals, which I think is much nicer than concatenating lots of literals and variables together to get the output you want. Template strings are surrounded by a pair of backtick characters. I know they appear small here in my editor, and look a lot like the single quote or apostrophe character, but it's actually the backtick. Within the template string, you can include expressions that will be evaluated and inserted into the final string. Expressions begin with the $ and are then enclosed in curly braces. In this first expression, I'm beginning the string with the value in the title property of the object. In TypeScript, you must use the this keyword when referring to properties and methods in the same class. I then continue the string literal without any cumbersome concatenate, and add another expression at the end to print the year. Okay, that's all I'll add to the printItem method for now. In order to use the ReferenceItem class elsewhere in the app, I need to export it from this module just like I exported the UniversityLibrarian class. I'll just add this class to the same export statement. Let's now jump over to the app.ts file. I need to import the new class from the classes file, so I'll just add it to the import statement I already have for that file. I'll go to the end of the file so I can write some code that uses the new class. I'll first declare a new variable named ref, and assign it a new instance of the ReferenceItem class. You create new instances of a class by using the new keyword followed by the name of the class and any parameters expected by the constructor. I'm going to set the title and year properties and then call the printItem method. I'll start the build task, and then press F5 to run the app. I get two messages in the console. The first is the message I logged inside the constructor, so we know that is when our object was being created, and the second is the result of calling the printItem method, which used the template string to output the title and year of the item. I'll return to the editor, and I'm now going to open the classes.ts file on the left side, and app.ts on the right side. Remember that all class members are public by default. I'm going to explicitly make year private by adding the private keyword in front of it. Notice that when I do that I immediately get an error in the app.ts file where I'm trying to assign a value to the year property. I'll hover over it and see that the error message is very clear, Property 'year' is private and only accessible within class 'ReferenceItem'. I want to implement these properties a little differently, so I'm going to delete these two lines of code that use them here. I want to pass the values they should contain to the constructor, so I'll modify it to accept two parameters named newTitle and newYear. I'll then assign those parameters to the properties inside the body of the constructor. If we now turn our attention back to the app.ts file on the right, we can see that I have a new error on the line that creates the new ReferenceItem. It says Supplied parameters do not match any signature of call target. That's a fancy way of saying, I'm not passing the parameters expected by the constructor. It now expects a string and a number parameter. Each class can only have one constructor, but if we want some flexibility regarding what parameters we pass to it, we can always specify that the parameters are optional. I'll add a question mark after both of the parameters on the ReferenceItem constructor, and you can see that the error in app.ts goes away. In this case I want them to be required, so I'm going to remove the question marks. I'll then pass a title and year to the constructor when I create the new instance. I'll run the app again, and I get similar output, but with the new title and year I used. I'll stop the debugger and close some of these extra windows. Since all I'm doing with the constructor parameters is assigning them to properties, I'm going to convert them to be parameter properties. I'll add the public keyword in front of the first parameter, and rename it to be title. I want to keep year private, so I'll add the private keyword in front of it and change the name to year. I can now delete the two lines inside the constructor that set those values, and the two property declarations inside the class. This is just a more concise form of what I had before. There will be a public property on the class named title, and a private member named year, which is only accessible inside the class. I'll go back to app.ts and change the parameter values before running it again. While I'm here, I want to point out that classes, like interfaces, define types. I didn't initially add a type annotation to this ref variable. The TypeScript compiler inferred that it's of type ReferenceItem, since that's what I assigned to it. However, just to prove I can use a class as a type, I'll add the annotation now. That works fine, and I don't get any red squigglies. I'll run the app, and it shows the updated title and year, so we know I implemented the parameter properties correctly. I want to add another property to the ReferenceItem class, but I want to implement this one with accessor functions. I'll start with a new private variable named _publisher. There's nothing significant about the underscore, other than it differentiates the name of my backing variable from the name of my accessor functions, which will be publisher without the underscore. Getters begin with the get keyword, followed by the new property name and an empty set of parentheses. Specifying a type is optional, but I'll add one. Inside the body of the getter, I can add any custom logic I need. I'm going to keep it very simple and just return the private backing variable converted to uppercase. I now need a setter. It begins with the set keyword and must take exactly one parameter. I'm specifying a type for that parameter, but you must not specify a type for the setter itself. The closing parentheses around the parameter is immediately followed by the curly braces surrounding the body. In the body, I'll just assign the new value to the backing variable, remembering that I must use the this keyword in front of all class members. Okay, the accessors have effectively created a new property on the class named publisher. Let's go back to app.ts and try to use it. You can see that when I type the dot after my variable name, the code completion help recognizes the new publisher property. I'll assign a string to it which will exercise the setter, and then I'll log the property to the console, which will exercise the getter. I'll run it again, and we can see that the assignment was obviously made correctly, and that the logic inside the getter ran and returned the string in all uppercase. The last thing I want to quickly show you in this demo is how to add and use a static property. Back in the ReferenceItem class, I'll add a new static property named department, and initialize it to 'Research'. It looks like any other property, except for the static keyword in front of it. To see how using it is different from instance properties, I'm going to add a second log statement to the printItem method. It uses another template string to log the value in the static property. Because it's a static property, it's only available on the class, not on instances of the class. I refer to instance properties inside the class by prefixing them with the this keyword, but the static property must be prefixed with the class name. Since our test code already calls the printItem method, I can just run this again to see the results. It does correctly log the Department. Okay, time to move on to a discussion of inheritance and how to extend classes in TypeScript.

  51. Extending Classes with Inheritance Inheritance is a means for one class to share its member definitions with one or more subclasses. That's about the simplest definition I can come up with. Let's suppose I created a class named ReferenceItem and gave it the properties title and year, as well as a method named printItem. I might then create two additional classes named Encyclopedia and Journal, that both inherit from ReferenceItem. In this scenario, ReferenceItem would be the parent class. Another term you'll often here is super class. Encyclopedia and Journal are the child classes, or subclasses. New instances of the child classes will have all of the properties and methods from the parent class, as well as any properties or methods explicitly added to the child class. Therefore, in this example, Encyclopedia objects would have title, year, edition, and numberInSet properties, and a prinItem method. The Journal class would also have title and year properties, but instead of edition and numberInSet, it would have its own properties, contributors and issueNumber. It would also have the printItem method. Inheritance facilitates code reuse since common members are only created and maintained in one place. Implementing inheritance in TypeScript is pretty straightforward. Let's look at an example using a couple of the classes from the previous slide. I'll start with the ReferenceItem class. There's nothing particularly special about it. It's just a normal class with a title property and a printItem method. I left off the year property in this example just to save a little space on the slide. The Journal class will inherit from the ReferenceItem class. That relationship is defined using the extends keyword. The Journal class will extend the ReferenceItem class. The restful will be that instances of the Journal class will have a title property and a printItem method inherited from ReferenceItem, as well as a contributors property defined in its own class. The last new bit of code in this example is the call to a function named super inside the Journal constructor. Super is a keyword that refers to the parent class. Classes aren't required to implement constructors, but if a child class has one, then it's required to call the parent's constructor using super as I've done here. You must do that even if the parent hasn't defined a constructor. If the parent's constructor expected some parameters, you would pass them the super as you would to any other function. However, if the parent's constructor expected some parameters and the child class didn't define a constructor, the parameters expected by the parent must be passed when creating new instances of the child class. Let's now go implement inheritance between some classes in the demo app.

  52. Demo - Extending Classes In this demo, I'll define a simple inheritance hierarchy in the LibraryManager app and experiment with some of the details related to calling constructors correctly. I'm going to start back in the classes.ts file and extend the ReferenceItem class I created in the last demo. I'll call the new class Encyclopedia, and use the extends keyword followed by the name of the class it will extend. I'm just going to give the class one additional property for now named edition. Before I can use the new class in other modules, I need to add it to the list of exports here at the bottom. I'll now open app.ts and add it to the list of imports from the classes module. Okay, I can now jump to the end of the file and start using it. I'm going to comment out this code from the last demo. I'll declare a new variable named refBook and set it equal to a new instance of the Encyclopedia class. Since it extends the ReferenceItem class, it has a method on it named printItem. I'll call it here so we can see some output. We can't run the code yet, because I obviously have an error here, Supplied parameters do not match any signature of call target. All child classes must call their parent's constructor. Since I didn't explicitly specify a constructor on the Encyclopedia class, it's implicitly using the one defined on the parent ReferenceItem class. That constructor expects two parameters, title and year, which is what this error message is trying to tell me. I'll get rid of the error by passing what it expects. I can now run the code. As expected, it output the messages being logged inside the printItem method. Perhaps more interesting is the message that it's creating a new ReferenceItem. Remember that I added that log statement to the ReferenceItem constructor, so this is proof that it's being called, even though it was the Encyclopedia subclass that I instantiated. I'll now go back to the Encyclopedia class and add a constructor to it. I want it to accept three parameters, a title, year, and edition. Since this subclass now has its own constructor, I must call the super class's constructor inside it. The ReferenceItem constructor takes two parameters, as we just saw, so I'll just pass along the title and year sent to the Encyclopedia constructor. Notice that I used the public keyword to treat edition as a parameter property, so I no longer need the declaration I added earlier. I'll go back to app.ts, and I now have an error there because I'm not passing enough values to the new constructor. I'll add a third one to set the edition property to 10. Just to quickly show you that this object has all the properties and methods from its parent, as well as its own, I'll just let the code completion show us the list. You can see the edition property specific to Encyclopedia, as well as all the members on ReferenceItems. Okay, back in the classes file, I want to show you how we can override methods inherited from a parent class. If I wanted the printItem method to behave differently in the Encyclopedia class than it does when inherited from ReferenceItem, I can just redefine it in Encyclopedia to do whatever I want. In this case, I want it to do everything the version in ReferenceItem does, plus some extra stuff. I can call the ReferenceItem version by using the super keyword in front of the method name instead of the this keyword. This will instruct TypeScript to call the version of the function defined on the super class. Once it's done executing, my additional log statement here will print out the edition. Unlike constructors, I'm not required to call the super class's version of a method when I override it. I can comment out that line, and everything is still fine, no red squigglies. However, I want it to call that method so I'll leave it in there. I'll run it again, and we can see the log statements output from the call to the super class's printItem method, as well as the additional line I added to the subclass's version. I think it would be nice to print the year in parentheses after the edition, so I'm going to modify the log statement to include that. That's giving me an error, and if I hover over it I'm reminded that year was declared as private inside the ReferenceItem class. To fix that, I'll scroll up to where year is defined on the ReferenceItem constructor. Private members are only available in the class in which they're declared. I'm going to change this from private to protected. Members declared with protected are also available in subclasses of the class in which they're declared, however, they're still not available publicly. I'll scroll down, and we can see the year went away. I'll run the app one more time, and we do now get the year in parentheses. Just to show you that year is still hidden from public view, I'll go back to app.ts and use code completion to show you the available members again. Year is still not available. It's only accessible inside ReferenceItem and Encyclopedia. Now that you've seen how inheritance works in TypeScript, we're ready to talk about abstract classes.

  53. Abstract Classes Abstract classes are a special type of class. You create one by adding the abstract keyword in front of a class definition. They're similar to regular classes, but they may only be used as base classes from which other classes are derived via inheritance. You can't directly instantiate an abstract class. In that way they're similar to interfaces, however, unlike interfaces, abstract classes may contain implementation details such as function bodies and accessors. Within an abstract class, you can define abstract methods that are not implemented. Abstract methods must be implemented in derived classes. Let's convert the ReferenceItem class in the demo app to be abstract, and experiment with some of these features.

  54. Demo - Creating Abstract Classes In this demo, I'll create an abstract class and show you how to use it as a base class for other classes. I'm in the classes.ts file, and I'm going to convert the existing ReferenceItem class to be abstract. That's as simple as adding the abstract keyword in front of the class definition. This class remains syntactically correct, since abstract classes may contain fully-implemented properties, constructors, methods, and accessors. This one has all of those. I'm not going to add an abstract method at the end of it. I'll call it printCitation, and it won't take any parameters, and will return void. The idea behind the method is that different types of ReferenceItems must be cited differently when referenced in academic papers. Since the format used when citing an encyclopedia is different from that used when citing a newspaper, for instance, I don't want to provide an implementation for the printCitation method here. It should be implemented by classes that inherit from ReferenceItem. Therefore, I mark it abstract here, which forces subclasses to provide an implementation. We can already see that I'm getting an error on the Encyclopedia class below as a result. I'll hover over it and see that it does not implement inherited abstract member 'printCitation' from class 'ReferenceItem'. That's a pretty clear error message. To fix it, I'll scroll down to the end of the class and provide an implementation. I'll just have it log the title followed by a dash and the year. To be clear, this is not the correct way to cite an encyclopedia. Don't use this format on your next term paper. I'm keeping it short for demo purposes. Now that I've implemented the method, we can see that I no longer have an error on the Encyclopedia class. Let's now jump over to app.ts and use it. The first thing I want to show you here is that I can no longer create new ReferenceItems. I'll uncomment this line of code from an earlier demo that created one. Abstract classes can't be instantiated, you can only create instances of their subclasses. I'll hover over this error and it tells us exactly that, Cannot create an instance of the abstract class 'ReferenceItem'. However, I can declare a variable to be of that type. Down below, I'm already creating a new encyclopedia. I'll add a type annotation to the variable and specify that it will be a ReferenceItem. That's perfectly valid. I could now instantiate any subclass of ReferenceItem and assign it to this variable. Encyclopedia is a subclass of ReferenceItem, so this works fine. I'll change the call to printItem to call the new printCitation method instead to demonstrate it. I'll run the app, and we see the very short citation in the console. From here, I'll go straight to a short demo on class expression.

  55. Demo - Using Class Expressions Class expressions are another ES2015 feature that TypeScript supports. In this demo, I'll show you a couple of different ways they can be used. The classes I've used so far have all been created with class statements. Class expressions are similar, in that they define a class, however, they can only be used where you might normally use other expressions. Giving a name to a class in a class expression is optional, and will only be available within the class if one is provided. Let's look at a couple of examples. I'm here in the app.ts file. The first thing I'm going to do is create a new variable named Newspaper, and assign it a class expression. Notice that the expression is nearly identical to a class statement. I've left off the optional class name in this case. The class defined by my expression will extend the ReferenceItem class and simply implement the abstract printCitation method. I can create new instances of the class using the variable that received the expression assignment. I'll create a new variable named myPaper and assign it a new Newspaper instance. Since the class defined by the expression extends ReferenceItem, whose constructor expects two parameters, I pass in the name of the paper and publication year. I'll call printCitation on the new instance, and then press F5 to run it. The expected result is logged to the console. Next I'll show you a bit of an extreme example of using a class expression anywhere a class is expected. I'm going to use a class statement to define a new class named Novel. I'm going to have it extend another class, but the class it will extend will just be the result of a class expression I'm going to define in line. I just use the class keyword and then define a class body inside curly braces. The base class will have one property named title. My Novel class extends that, and add one property named mainCharacter. I'll create a new instance of the Novel class, and then use the code completion support to show you that it does, in fact, contain the property it inherited from the class expression, as well as the one defined on itself. I can't think of a good reason to actually use a class expression as a base class like I did here, but I think it makes the point that class expressions can be used where any class definition is expected.

  56. Summary Classes are a very important part of TypeScript and provide all of the functionality required to make object-oriented developers feel right at home doing WebClient or Node.js development. In this module, I talked about what classes are and how to use them in TypeScript. We saw all of the different members a class can contain, including constructors, properties, methods, and accessors. I also covered inheritance and how to implement it in TypeScript by extending classes. Abstract classes provide a nice way to define base classes that contain functionality to be shared across multiple derived classes. I wrapped up with a brief look at class expressions and how to define and use them. In the next module of the course, I'm going to cover TypeScript modules and namespaces. I've already given you a brief look at modules when I began splitting the demo app into multiple files. We all know that it's not practical to keep all of your code in one file, and that it makes sense to define, encapsulate, and share reusable chunks of functionality. We'll see how to do that with modules and namespaces next.

  57. Modules and Namespaces Introduction and Overview Hi, this is Brice Wilson. In this module I'm going to cover modules and namespaces. We all want to write well-organized and reusable code, and these are the two features in TypeScript that help us do that. The definition of modules in TypeScript has evolved over time, so I'm going to start with a brief history lesson about modules so you're at least familiar with some of the older terms that were used to refer to modules and namespaces. I'll then talk about some of the high-level differences in modules and namespaces, and when you might want to use one over the other. After that we'll get into the details and see how to create and use namespaces, and then do the same thing with modules. Let's get started.

  58. Changes in TypeScript 1.5 Before I get into the details of how to use modules and namespaces, I need to give you a quick history lesson in how these two constructs have evolved in TypeScript. TypeScript version 1.5 introduced major changes in both terminology and syntax related to modules. I want you to be aware of that so that when you run across older Stack Overflow questions or blog posts that use these terms, you'll recognize them and hopefully understand how they apply to more modern TypeScript. Prior to version 1.5, TypeScript had both internal and external modules. They were really used for different things, but because they were both called modules, it was easy to get confused about the differences and when to use each kind. Beginning with TypeScript 1.5, internal modules became known as namespaces and external modules became known simply as modules. I'm not going to cover the older syntax for defining internal and external modules, it's still valid, but really only for the sake of backward compatibility. Any new code you write should use the new syntax, which I am going to cover. The other major change related to modules that was introduced with TypeScript 1.5 was support for the ECMAScript 2015 module syntax. ES2015 is the first version of JavaScript to have native support for modules, and TypeScript has adopted the same syntax. It's very clean, and should make reading code when moving between TypeScript and JavaScript in the future, much easier.

  59. Modules Versus Namespaces Let's now quickly look at some of the similarities and differences between modules and namespaces. The one thing I think you can say about both of them is that they're both tools for organizing your code. Modules go beyond that and allow your TypeScript code to be output in various module formats that can then be loaded as needed at runtime by a JavaScript module loader. Node has native support for loading modules defined with the CommonJS format, which the TypeScript compiler can output. You can also load modules in browsers with the help of a separate module loader. Eventually I suspect most browsers will build in support for loading ES2015 modules natively, but until that day comes there are several different loaders like Require.js and System.js that can help you do that today. I mentioned earlier that TypeScript modules support the new ES2015 modules syntax. They also facilitate code reuse, and definitely appear to be the future when it comes to splitting up your code and developing reusable pieces of functionality. That is not to say that namespaces don't have their place. They are generally much simpler and don't require a special loader to use them in browser applications. Beyond their simplicity, their main benefit is that they prevent global namespace pollution. Functions and classes can be housed inside a namespace, which means you have fewer things to find globally. However, as I mentioned, modules are the future and come with lots of nice benefits, but if you're going to be building smaller browser-based applications, namespaces are a great option. Now let's see how to create and use them.

  60. Creating and Using Namespaces Namespaces are created using the namespace keyword followed by the name you want to give the namespace. The contents of the namespace are enclosed in curly braces. You can expose functions, classes, interfaces, or even simple values from a namespace. Here I've defined a new function named AddMember. I expose it on the namespace by putting the export keyword in front of the function definition. Consumers of the function can then access it through the namespace using dot notation. Namespaces can also be nested. A nested namespace must also be prefixed with the export keyword. You can then export objects from the nested namespace just like you do from the root namespace. Since the AddMember function is in the Membership namespace, I call the function by writing Membership.AddMember. The nested namespace just adds one more level to the dot notation. I can call the IssueCard function by writing Membership.Cards.IssueCard. When organizing your application with namespaces, you specify that one file is dependent on items defined in another file by using what are known as "Triple-Slash" references. They are called that because they begin with three slashes. Those slashes are then followed by what looks like an html element named reference. It has an attribute named path that specifies the path of the file to be referenced. Here I'm referencing a file named "membership.ts", which holds the namespace I created on the previous slide. Once you've referenced all of the necessary files, you can write whatever code is needed that uses the items defined in those files. In this example I'm calling the functions I defined inside the Membership namespace. Using triple-slash references does a couple of very nice things for you. The first is that you get enhanced editor support for the referenced files, assuming you're using a TypeScript-aware editor. Your editor can see the things defined inside the referenced files, and give you nice code completion support for them. The second thing it does is tells the compiler what additional files must be compiled in addition to the present one. For example, if the code you see here was in a file named app.ts, and I just told the TypeScript compiler to compile that file, it would see the reference to membership.ts and automatically compile it as well, since it's required by app.ts. By default, each of the TypeScript files would still be compiled into their own JavaScript file. In the case of a browser application, that would mean you would have to add separate script tags for each of the JavaScript files and list them in the correct order so that they would be available when referenced. However, you can let the TypeScript compiler handle some of that messiness for you by using the --outFile compiler flag. It will compile the files you specify and follow all of their referenced files and output them to a single JavaScript file with everything in the proper order. That's a very nice feature you'll want to take advantage of if you're using namespaces. Let's now go whip up a quick new demo app that uses namespaces.

  61. Demo: Creating an App with Namespaces In this demo, I'm going to show you how to use namespaces in TypeScript. Since the demo app I've used so far in the course is already configured to use modules, I'm going to start from scratch with a super-simple new project. I'm going to start here in the terminal by creating a directory for the new application. I'm going to call it NamespaceDemo. I'll go into the new directory and start Visual Studio Code from there. I want to create a new file that will contain several utility functions that can be used throughout the app. I'll name it utilityFunctions.ts. I don't want to just add all the functions to the global namespace, so I'm going to define a TypeScript namespace and put them inside it. I use the namespace keyword followed by the name of the new namespace, I'll call it Utility. The contents of the namespace go inside the curly braces. I'll further categorize my functions by defining a nested namespace inside utility named Fees. Notice that the syntax for it is the same, with the exception of the export keyword that exposes it on the Utility namespace. I'll now write my first function and name it CalculateLateFee. I'll use it to calculate small fees that are owed when books are returned late to the library. It will take the number of days that the book is late as a parameter and return the amount of the fee. I'll set the fee to be .25 cents per day. Just like I did with the Fees namespace, I also have to put the export keyword in front of the function to make it available on the namespace. I'll now come down just a bit and use a code snippet to paste in a couple more functions. These are defined outside the Fees namespace, but they're still a part of the Utility namespace. The MaxBooksAllowed function calculates the maximum number of books that may be checked out based on a person's age. Kids less than 12 may only check out 3 books, everyone else can check out up to 10. Again, I exported this function from the namespace. I did not export the last function, which I only added as an example of not using the export keyword inside a namespace. This effectively becomes a function that is private to the Utility namespace. I can call it from inside the namespace, but it won't be accessible outside it like the functions I've exported. Now that I've got a couple of Utility functions defined, I'll add a new file and write some code to call them. I'll name the file app.ts. If I open the new file and immediately try to call one of the new functions using the Utility namespace and the dot notation, you see that it's not working. I'm not getting any code completion help, and Visual Studio Code doesn't seem to know what Utility refers to. I need to add a triple-slash reference to the file containing the namespace. Visual Studio Code comes with a code snippet named ref that will paste in a reference. I'll specify utilityFunctions.ts for the path attribute. With that in place, I can start typing the same line of code again, and you can see that Visual Studio Code is giving me lots of helpful information. I can see that the Utility namespace contains another namespace named Fees and a function named MaxBooksAllowed. Notice that I don't see the private function that I didn't export from the namespace. I'll call the CalculateLateFee function inside the Fees namespace, and assign it to a variable. I'll then just log the value in the variable. Everything looks good, but I want to show you one little trick that can reduce the amount of typing you have to do if you need to call a bunch of functions nested inside namespaces. You can use the import keyword to define an alias for a namespace. I'm going to create an alias for the Utility.Fees namespace and name it util. You just use the import keyword followed by the name of the alias, and assign it the fully-qualified namespace. With that in place, I can now change the code below to just call util.CalculateLateFee. Okay, let's try compiling and running this code back in the terminal. Remember that the TypeScript compiler is just named tsc. I'll use the --target option to tell it to output ES5 JavaScript, and then tell it to compile just app.ts. This only takes a second to run. I'll type ls so we can see a list of files that are now in this directory. In addition to the original TypeScript files, app.ts and utilityFunctions.ts, I also have JavaScript versions of both files, even though I only instructed the compiler to compile app.ts. That's because the compiler saw the reference to utilityFunctions.ts inside of app.ts and automatically compiled it as well. I'm now going to try to run the program by typing node app.js. That gives me an error. Node doesn't recognize the Utility namespace which was defined in another file. That's because node wants to load multiple files using modules, not namespaces. However, I will point out that the way I built and compiled this would work fine for a client-side web application. I've got two JavaScript files, I could just add a script tag for utilityFunctions.js first and then another one for app.js, and it would all work great. This can be made to work with Node though. As I mentioned in the slides, we can use the --outFile compiler option to have all of the required source files compiled into a single output JavaScript file. I'll bring up the tsc command again and just add to the end of it --outFile out.js. It should now compile both TypeScript files and produce one output file named out.js. I'll use Node to run that file, and you can now see that it works correctly.

  62. Reasons to Use Modules Let's now turn our attention to modules. There are lots of good reasons to use modules in your TypeScript apps. First of all, they're modular. We developers are always in search of more modularity. This really boils down to a search for ways to make our code more maintainable and reusable. I think TypeScript modules deliver on both counts. Modules are also native to both Node and ES2015, and TypeScript compiles to formats supported by both of those. One of my favorite features of modules is that they're organized very simply using the file system. Each file is a module and can be nested in appropriately-named directories. They're very easy to explore with editors and from the command line.

  63. Module Formats and Loaders I think the number one reason many people find modules in TypeScript and JavaScript so confusing is that there isn't a single module format. Modules tend to be spoken of and written about very generically, and it all seems to make sense until you sit down and realize there are several different ways they can be written, and you quickly get lost in the weeds trying to figure out syntax issues and which modules format runs in what environments. Trying to sort all of that out is beyond the scope of this course, but I hope that you'll be relieved to hear that TypeScript can compile to all of the most popular modules formats using the--module compiler flag. In this course, I've been running the demo app using Node, and Node uses the CommonJS module format. A popular module format for browser apps is the asynchronous Module Definition format, which is usually just abbreviated AMD. This format is often used in conjunction with the Require.js module loader. TypeScript can also output to the Universal Module Definition format. This format combines the CommonJS and the AMD formats. JavaScript produced in the UMD format can be loaded by both Node, and loaders that support the AMD format. System JS is a very popular module loader that supports the CommonJS and AMD formats. It also defines its own custom format. TypeScript can output to it by passing system to the --module flag. Finally, since TypeScript can output to ES2015, which defines its own module format, TypeScript can produce modules in that format as well. It's important to remember that these are all JavaScript module formats that the TypeScript compiler can produce. When you actually sit down to write and consume modules in TypeScript, you'll be writing them using the ES2015 syntax that TypeScript adopted. Before I start covering the syntax for using modules, I want to briefly mention module loaders. Node has a built-in module loader. By that, I mean that it understands the CommonJS format and how to retrieve all of the necessary dependencies when running code written in or compiled to that format. As I'm recording this in 2016, browsers don't provide that capability natively. However, there are a couple of very good libraries that give you the ability to load and use modules in browser apps. Require.js is very popular and has been around for quite a while. It supports the AMD module format, so you can easily output your TypeScript so that it can be loaded with Require in a browser. SystemJS is another popular client-side module loader. It's very flexible and supports AMD, CommonJS, ES2015, and its own system format. If you're writing TypeScript to be compiled and run in a browser, then these are both very good options for loading client-side modules. Okay, let's now dive into the syntax for creating modules in TypeScript.

  64. Exporting from a Module Here I have the complete contents of a file named periodicals.ts. The only thing I have to do to make this file a module is export something from it. Items in the module are only available to be used in other modules if they are exported from this module. In this example, I'm using export declarations to export an interface, a class, and a function. Export declarations are the simplest way to export something from a module. You just add the export keyword in front of any declaration. Another way to export items from a module is to use what is known as an export statement. I'll now change the code on this slide to export all of the same items with an export statement, instead of the export declarations. I've removed the export keyword from the front of the interface, class, and function. Their definitions are otherwise exactly as they were before. I'm now exporting the items using an export statement at the end of the file. You just add the export keyword, followed by a list of the items to be exported inside curly braces. This is the technique you've seen me use in other modules of this course so far. I prefer it when there are several items that need to be exported. I like knowing I can quickly glance at the end of the file and easily find the list of things being exported without having to visually scan the entire file. Another small benefit of using export statements is that they allow you to export items with a name other than the one assigned to it when it was declared. I'm doing that here with the GetMagazineByTitle function. I use the as keyword after the name of the function to export it with a different name. GetMagazineByTitle will now be known as GetMag when imported into other modules. The importing module can also give it a new name, and we'll see how to do that in just a minute.

  65. Importing from a Module Let's now see how we can import the items exported from the module shown on the last slide. Let's suppose I'm in another file named news.ts. I can import items from the periodicals module by typing the import keyword followed by a list of the things I want to import in curly braces. You're not required to import everything that the module exports. The periodicals module included an interface named periodical, but I don't need it in this module, so I didn't add it to the list of imports. You can use the as keyword when importing to change the name you'll use to refer to a specific item being imported. In this module, I'll refer to the GetMag function as GetMagazine instead. The last part of the import statement specifies where to find the module. You just add the from keyword followed by the relative path to the source code file for the module. You leave off the file extension. In this example, the items will be imported from the periodicals.ts file, which is in the same directory as the current file. Once the items are imported, you can use them with the names imported or assigned during the import. Another option you have when importing from a module is to import the entire module and give it a single name during the import. A given module doesn't have to be imported the same way every time it's used. I imported two individual items from the periodicals module in the news.ts file above, but in this snippet from the kids.ts file, I'm going to import the entire module. To do that, I type the asterisk character after the import keyword, and then give it a name. Here I'm importing the entire module and referring to it as Mag. I specify the location of the module using the from keyword and a relative path to the file, just like I did in the previous example. Importing the entire module like this means that the individual items exported from the module will be available as members on the alias I gave it. For example, I referenced the Magazine class in the GetMag function by prefixing them with mag and a dot, since that's the name I gave the module when I imported it. Let's go some examples of these techniques in the demo app.

  66. Demo: Export and Import Basics In this demo, I'm going to show you how to create export declarations, and then import the exported items into another module. I'm going to start by making a copy of the file containing some utility functions I used in the namespaces demo. I want to put in a new directory inside the LibraryManager project named lib, so I'll create that directory now. I'll go into the new directory and then copy the file from the NamespaceDemo directory. I'll now go back to the LibraryManager app inside Visual Studio Code, and open the utilityFunctions.ts file that's inside the new lib folder. This is the same file I used in the namespace demo, but I now want to use it as a module, so I need to do a little cleanup work on it to get rid of the namespaces. I'll delete the outer Utility namespace, as well as the nested Fees namespace. With the namespaces removed, I'll just fix the indentation issues, and it's ready to begin a new life as a module. Notice that I'm using export declarations to export two of the functions in the module. Exporting them just requires adding the export keyword in front of the function declaration. The same would be true if I were exporting classes or interfaces. Also notice that I haven't added the export keyword to the last function in the file. Because it's not being exported, it won't be available to be imported in other modules. You may have noticed that I have the dreaded red squiggly under the CalculateLateFee function. That's just Visual Studio Code reminding me that I cannot compile modules unless the --module flag is provided. I have set that compiler flag on the build task I have configured, so I can safely ignore this particular squiggly. I'll now open the app.ts file so I can import these functions and show you an example of using them in another module. I'll close the sidebar just to give myself a little more room. I need to add a new import statement at the top of the file so I can access the new functions. Just to demonstrate how you can control the name used to refer to imported items, I'm going to use the as keyword and specify I want to refer to CalculateLateFee simply as CalcFee inside this module. I'll import the MaxBooksAllowed function with its original name. I have to specify the location of the module containing these functions, and since I put it in a folder named lib, I have to make sure I include that in the path. I'm going to create a couple of new variables and assign them the return values of the functions. Notice that as I start typing the CalcFee function, Visual Studio Code recognizes that as the alias I gave the CalculateLateFee function. I get the same kind of help with MaxBooksAllowed. Okay, I'm not going to run this, I just wanted to demonstrate how to write and rename the functions on the import, and show the editor support I'm getting for them.

  67. Demo: Importing an Entire Module In this demo, I'm going to declare exports using an export statement, and then show you an example of importing an entire module. I'm here in the interfaces.ts file I created in an earlier course module. You can see that I didn't use the export keyword in front of the interfaces. Instead, I used an export statement at the bottom of the file. It just lists the names of the items in the module that I want to export, inside curtly braces. The file contains five interfaces, but I only chose to export four of them. I didn't export the Person interface, since it was really just a base for the Author and Librarian interfaces. That's proof that you don't have to export everything, you can be selective. I also want to show how you can export an item with a different name. It's very much like giving an item a different name as a part of an import. You just add the as keyword and then provide the new name. I'm going to change this to export the DamageLogger interface as Logger instead. Let's now go over to the classes.ts file and see how we can import the interfaces. I've already got an import statement here for the interfaces. It's reporting a problem trying to import DamageLogger because I changed it to be exported as Logger. Rather than make that simple change here, I'm going to modify the import statement to import the entire module into a single variable. I just need to replace the list of items with an asterisk followed by the name I want to assign to the entire module. I'll call it Interfaces. I can now get to the individual items exported from the module by referencing them as properties on the Interfaces variable. We can see the first place I need to do that right here below the import statement. The UniversityLibrarian class is attempting to implement the Librarian interface. Now that I'm importing the entire Interfaces module, I need to change this to use the new variable. I'll type interface., and you can see that I still have access to the same four items being exported from the module. In this case I'll select Librarian, and it gets rid of the error. I also imported interfaces in app.ts, so I'm going to jump over to it now. Just because I imported the entire module in the last file, doesn't mean I have to do that everywhere. I'm going to let this file continue to import the individual interfaces, but I do need to change it so that it now imports Logger instead of DamageLogger. Okay, that's better. Let's now go see how to create default exports.

  68. Default Exports The last type of export I want to cover are default exports. They accomplish the same thing as the other exports we've seen, but their use case and syntax are just slightly different. Default exports are most useful when you only want to export one item from a module. Once you've specified that item as the default export, other modules can import it without even knowing its name. In this example, I've got a file named movie.ts and I'm exporting a single class from it. Notice that this looks like any other export declaration with a couple of small differences. The first is that I've added the default keyword after the export keyword and before the actual declaration. The second is that I didn't provide a name for the new class. Assigning a name to a default export is actually optional since the importing module doesn't need to know its name. I can import this new class in another module using an import statement very similar to the others we've seen. You just use the import keyword, followed by the name you want to give the default export, and then specify where it can find the module. I'm going to refer to the new class here as AnimatedMovie. Since there can only be one default export, I don't need to surround the name with curly braces. Once I've got it imported, I can create new instances of the class using the name I gave it just like any other class. Let's go see one more example of this in a demo.

  69. Demo: Using Default Exports In this demo I'm going to move the Encyclopedia class I created earlier in the course into its own module and make it the default export from that module. Okay, I'm in the classes.ts file. I'm going to highlight the Encyclopedia class and cut it out of here so I can move it to its own file. Before I leave this file, I need to remove Encyclopedia from the list of exports at the bottom. I'll now create a new file and name it encyclopedia.ts. I'll paste in the class definition. Since it extends the ReferenceItem class, I need to import it at the top of the file. Okay, because I only have one item I want to export from this module, I'm going to make it the default export. To make it the default, I just have to add export default in front of the class definition, that's it. I could remove the name of the class if I wanted since it's optional, but I'm just going to leave it. Let's now go back to app.ts and import form the new module. I've got an error here because Encyclopedia is no longer in the classes module. I'll just delete that and add a new import statement to get it from the new module. Because the encyclopedia class is the default export from the new encyclopedia module, I can import it just be specifying the name I want to give it, and the location of the module. I'm going to import it as refBook. I can now use it like I would any other class. I'll create a new instance of it by writing new refBook, and pass the three parameters expected by the constructor. It all looks good. No red squigglies. Default exports are a great way to export items when you only have one item to export per module. They're also the easiest to import, since you don't have to know or care about the name used when the item was exported.

  70. Summary In this module, we saw various ways you can structure your code using modules and namespaces. I began with a quick history of modules in TypeScript. As their usage evolved, so did the nomenclature around them. As a final reminder, what used to be known as internal modules are now known as namespaces, and external modules are now simply modules. I also talked about the primary differences between modules and namespaces, and when you might choose one over the other. Namespaces are certainly the simpler of the two, but they're really only appropriate for relatively small client-side web applications. Modules are definitely the future, and should be your default choice for most projects. I also covered the syntax for creating and using namespaces and modules. They're both useful tools to help you keep your code organized and maintainable. Well-organized code is often a requirement of reusable code, and reusability should be the goal of every module. Reusability is also an underlying theme of the next course module. I'm going to cover how to use generics in TypeScript, and show you how one bit of code can be written to work with many different types. Stay tuned for that.

  71. Generics Introduction and Overview Welcome back. This is Brice Wilson. In this module I'm going to cover generics and show you how you can write functions, classes, and interfaces once, but have them operate over lots of different types. I'm going to start this module by defining generics and why they are useful. That will naturally lead to a discussion of type parameters, since they're the construct used to define generics. From there, I'll show you how to use generic functions, as well as generic classes and interfaces. I'll wrap up the module by showing you how to apply constraints to generics so that they only work over a subset of all possible types.

  72. What are Generics and Type Parameters? So what exactly are generics? Probably the simplest answer I can give to that question is that generics are bits of code designed to work with multiple types instead of a single type. Generics are able to work with multiple types by accepting type parameters that specify which type it should use for a particular variable instance or function invocation. By applying type parameters, you can create generic versions of functions, interfaces, and classes. You now know you can create generics with type parameters, but that just leads naturally to the next question. What are type parameters? Type parameters are a special kind of parameter that let you specify the type that a particular instance or function invocation will use. A single generics class may be instantiated several times, each time with a different type. The type passed to the type parameter determines the type that instance will use. Type parameters are listed separate from function or constructor parameters. They're passed inside angle brackets just before the parentheses surrounding function parameters in the case of a generic function call. The placeholder for a generic parameter is conventionally represented by a 'T' as a one-letter abbreviation for the word 'type', however, this isn't a requirement, and you can use any letter or word you like. Just as values for function parameters are provided when the function is called, the actual type that will be used with a generic is provided when the generic is used.

  73. Using Array TypeScript includes a generic array type that you'll probably find yourself using quite often. Since you're hopefully familiar with how arrays work in general, array should give you a very relatable introduction to using generic types. In this first line of code, I've declared a new variable that will be an array of books. I can accomplish the same thing using the array type. In this second line, I've also declared a new variable that will be an array of books by specifying book as the type parameter inside the angle brackets. An important thing to note about this second example is that all I've done is specify a type for the new variable. This is significant because it highlights the fact that the type parameter is part of the type. It declares that the fictionBooks variable will be an array that can only contain books. The array class also contains a constructor like many other classes. In this last example, I'm creating a new array of books that will initially contain five elements, and assigning it to the variable. TypeScript will use type inference to determine the type of the new variable. The bit I want to highlight here is that the type parameters are listed separate from the function parameters. The Book type parameter appears inside angle brackets, and the function parameter appears after that in parentheses. I'll show you how to create your own generic classes in a few minutes, but let's start by seeing how to create generic functions.

  74. Generic Functions Generic functions accept a type parameter that is either specified or inferred by the compiler every time the function is invoked. Here I've created the shell of a very simple generic function named LogAndReturn. The function will accept one type parameter, specified here in the angle brackets with the letter . I can specify that the type provided for T when the function is called should also be used elsewhere in the function by using the same T placeholder. For instance, I want the function to accept a parameter that will be of the type specified by the type parameter, so I've listed the type of the function parameter as T. I also want the function to return a value of that type, so I've also listed T as the function return type. I can also use T inside the function to declare new variables or do anything else that requires a type specification, but in this simple example I'm just logging the value passed to the function and then returning it. This is perfectly valid since the function must return a value with the same type it was passed. Here's an example of calling this function. Notice that I've specified string for the type parameter. In the function declaration, I specified that the function parameter and return value would both be of the type passed as the type parameter, and you can see that I'm passing a string literal to the function and I've declared that the variable receiving the return value will also be a string. As a quick example of calling it with another type, I'll declare a new variable of type Magazine, and then pass it to the function by specifying Magazine for the type parameter. Let's now go add a generic function to the demo app.

  75. Demo: Creating and Using Generic Functions In this demo, I'm going to add a generic utility function to the LibraryManager app. I'm going to add the new function to the utilityFunctions.ts file. I'll name it Purge and specify that it will accept one type parameter named T. It will accept one function parameter that I'll name inventory. It will be an array of items with the same type the caller specifies for . It will also return an array of that same type. The idea behind the function is that it will remove old items from an array of inventory items. It will return the items that were purged from the inventory. In a more real-world scenario, this function would implement some business logic to determine the oldest items and make sure they were the ones purged from the array. However, for demonstration purposes, I'm just going to use the splice function that's available on all arrays, and remove the last two items from the array. Those two items will be returned in an array from the purge function. The important thing to notice about the function definition is that whatever type is specified for the type parameter when the function is called will be the same type expected inside the array passed for the function parameter, and inside the array returned from the function. Let's now go over to app.ts and write some code to call the new function. The first thing I need to do here is add the purge function to the list of imports from the utilityFunctions module. I'll then jump down to the end of the file and use a code snippet to paste in a new variable named inventory. It's an array of books, and I've hard-coded four books into the array just to give us something to work with. Remember that the Purge function expects to be passed an array, so I'll call the function and specify Book as the type parameter and pass the inventory array I just created as the function parameters. Now that I've specified a type parameter for this particular function invocation, I can hover over it and see the call signature with the type expected for the type parameter. Since I'm passing book as the type, the signature shows that it should be passed an array of books, and that it will return an array of books. It does return an array, so I'll create a new variable named purgedBooks to receive the array of books purged from the inventory. Just to emphasize the importance of the type parameter, I'm going to change it from Book to number. I immediately get an error on the function parameter that tells me, argument of type book array is not assignable to parameter of type number array. I changed the type parameter to number, and TypeScript expects the function parameter to contain an array of that same type. I'll change the type parameter back to book. I get a similar error if I attempt to assign the function return value to an array of numbers. This time I'm told that type Book array is not assignable to type number array. This is really the same problem in a different place. Once I've set the type parameter, I have to make sure I use it consistently everywhere it's expected. I'll change the variable back to an array of books. The TypeScript compiler is always attempting to infer types when they're not specified explicitly. I can actually remove the type parameter from the function call, and it will still behave the same way. The compiler looks at the function parameter and infers the type being passed for the type parameter. If I hover over the function again, you can see that the signature hasn't changed. I'll now call the foreach function on the returned array and pass it an arrow function that will log the titles of the purgedBooks. I want to demonstrate that the same function can be used with other types as well. I'll call it again, passing number as the type parameter. Since the function expects an array of that type as the function parameter, I'll just pass a hard-coded array with four numbers. I'll also log the array of purgedNumbers, just so we can see that the function works for both types. I'll start the build task, and then press F5 to run the code. We can see in the console that it logged the titles of the two old books that are being purged from the array, as well as the numbers being purged from the numbers array. It would work just as well for any other type passed to the function. Let's now go see how to create generic interfaces and classes.

  76. Generic Interfaces and Classes Generic interfaces look a lot like non-generic interfaces. The only difference is the list of type parameters that appear after the interface name. The inventory interface only has one type parameter, but you can specify more than one by separating them with commas inside the angle brackets. Just like we saw with generic functions, T in this case will represent a type that will be specified when the interface is actually used. I can use T inside the interface anywhere I want to use the type it will ultimately represent. I'm going to add a few function definitions to the interface. getNewestItem will not take any parameters and will return a value of whatever type is specified for T, addItem will take a parameter of type T and return void, and getAllItems will return an array of whatever type is provided for T. When I'm ready to use this generic interface, I can declare a new variable and supply a type parameter for the type of thing I want to store in the inventory. I would need to assign it an instance of an object that implements that interface, but I can then work with it, knowing that the methods coded to work with type T will use Book for this particular instance. If I were to call the getAllItems method, it would return an array of books. Just like generic interfaces, generic classes are very similar to their non-generic version. The only real difference is the addition of a type parameter that can then be used inside the class. I've given this Catalog class one type parameter, but I've also specified that it will implement the generic interface from the previous slide. In this case, the T I provide for new instances of the class will be the same T expected for the implementation of the interface inside the class. In the body of the class, I'll declare a private variable to hold all of the catalog items. I'll declare it to be an Array. I'll then include all of the functions required to implement the Inventory interface. I only have room to show one of them here. I can create new instances of the class by using the new keyword followed by the class name and the specific type I want to pass for the type parameter. Any parameters expected by the constructor would appear inside the parentheses. Let's now add a generic class to the LibraryManager app that will be able to store lots of different types of library items.

  77. Demo: Creating and Using a Generic Class In this demo, I'm going to create a new generic class named Shelf that will be capable of storing different types of items inside the library. Before I create the new class, I want to add a new interface that we'll use with it later. I'll put it in the interfaces.ts file and name it Magazine. I'll give it two properties, title and publisher, both will be strings. Before I leave this file, I need to remember to export the new interface. I'm just going to add it to the list of other exports at the bottom of the file. Okay, I'm now ready to add the new Shelf class. I'll create a new file named shelf.ts. I'm only going to export one item from the module, so I'll make the class the default export. I'll name the class Shelf, and give it one type parameter named T. The simple idea behind this class is that there are lots of shelves in a library, and they may contain different types of library materials, books, magazines, movies, etc. By making my shelf class generic, I can pass the type of thing a particular shelf will hold as a type parameter when the shelf instance is created. Internally, the class will store the items in a private array. The array will store the same type specified for the Shelf class, so I declare it as an Array. Next, I'll use a code snippet to paste in a couple of methods. The first is named add. It will use the class's type parameter as well, to accept a function parameter of that type and then just push the new item onto the internal array. The getFirst method simply returns the first item from the internal array. It uses the type parameter as the function return type. Let's now go over to app.ts and experiment with the new class. I first need to import it from the Shelf module. I also want to go ahead and add Magazine from the list of imports from the interfaces module. Okay, I'll now jump down to the bottom of the file. I'm going to use the array of books I've assigned to the inventory variable, so I'll leave that there, but I'm going to comment out the lines below that call the Purge function. I want to store all of the inventory books above on a new bookshelf. I'll create a new variable named bookShelf, and assign it a new Shelf instance with Book specified as the type parameter. I'll use the foreach function on the inventory, and add an arrow function to call the add function from the Shelf class to add each book to the shelf. This works because inventory is declared as an array of books, and I specified Book as the type parameter for the bookShelf variable, and the add function expects to be passed a variable of that type. I'll add one more line here that calls the getFirst function I included in the Shelf class. Again, because Book was used as the type parameter for the Shelf, that's the type that will be returned from the function. The compiler would have inferred the type of the variable based on that, but I think this is a case when you should explicitly declare it since someone reading your code later may not know at first glance what type is returned from the getFirst function. I now want to show you an example of using the Shelf class with a different type. I'll use a code snippet to paste in an Array. Each object in the array implements the Magazine interface I created earlier. Below that, I'll paste in some more code that adds the magazines to a new shelf, just like I did with the books. The difference, which I'm sure you've guessed by now, is that I created the Shelf class with Magazine as the type parameter instead of Book. The Shelf class will currently work with any type. Just to demonstrate that, I'll create another instance of the class and use number as the type parameter. I'll then use a hard-coded array of numbers and add them to the Shelf. This is perfectly valid code, even if it makes no sense. The Shelf class is meant to represent a real-world object, and storing numbers on it is just silly. Making sure the Shelf class can work with any possible type also severely limits what we can do with it. To demonstrate that, I'll go back to the shelf.ts file and paste in a couple of new methods. The find method takes a title as a parameter and will search the shelf for the first item that has that title. The printTitles method just prints out the title of every object on the shelf. These are reasonable things to want to do with items on a shelf in a library, but as you can see I've got a couple of compiler errors here. They're both informing me that Property 'title' does not exist on type 'T'. That's true. Because T can currently be any type, I'm limited to using properties that exist on every type. That's a very limited use. Generic constraints are designed to address this issue, and I'll discuss them next.

  78. Generic Constraints Jon Stewart is a comedian that hosted a popular TV show in the United States for many years. I love this quote he gave in an interview once. I'm a real believer in that creativity comes from limits, not freedom." Although he was referring to the process of producing a television show, I like to think he would agree with me that the same idea applies to TypeScript generics. The real power of generics is only realized when they're constrained. Building functions and classes that work with any type has some value, but limiting the generic to a subset of all types opens up lots of new possibilities. Generic constraints describe the types that may be passed as a type parameter. Constraints are most often implemented as interfaces that describe the shape of types that may be used as a type parameter. Here I've defined a very simple interface named CatalogItem that has one property named catalogNumber. I'm going to use it to constrain the types that can be used with the Catalog class I defined earlier. I want to make sure that any type passed to Catalog has a property named catalogNumber. To do that, I use the extends keyword after the type parameter, and specify that T must extend the catalogItem interface. With that in place, I can only pass types to the class that have a catalogNumber property. Attempting to pass any other type will cause the compiler to generate an error. Let's now go back to the demo app and add a constraint to the Shelf class.

  79. Demo: Applying Constraints to Generics I'm now going to add a constraint to the Shelf class I created in the last demo, which will allow me to add some additional functionality to the class. In the last demo, I added the find and printTitles functions to the Shelf class, but the compiler quickly let me know that my type parameter T doesn't have a 'title' property. I'm going to fix that now by adding a constraint to the class. I'll start by creating an interface at the top of the file that contains all the properties I expect to be present on items stored on a shelf. I'll name the interface ShelfItem and just give it a title property for now. I then apply it as a constraint on the class's type parameter, using the extends keyword. T should extend ShelfItem, which means it must at least have a title property. Now that I've added that constraint, I no longer have errors when trying to refer to the title property in the find and printTitles functions. I'll now go back to app.ts. We immediately see that I now have a new error on my silly bit of code that tries to create a shelf of numbers. I'll hover over the error, and it tells me that Type 'number' does not satisfy the constraint 'ShelfItem'. That's because number doesn't have the title property I defined on the ShelfItem interface. That's fine, this code didn't make any sense anyway, so I'm just going to comment it out. I now want to try out the new functions I added to the Shelf class. I'll call printTitles on the magazineShelf instance. That's perfectly valid code since magazines have a title property. I'll then declare a new variable to hold the result of calling the find function to search for the book titled 'Code Complete'. I'll log the title and author of the book it finds. That code is also valid since book objects also have a title property. Just to prove it all works, I'll quickly run it. It output the titles of all of the magazines on the magazine shelf, as well as the title and author of the classic 'Code Complete'.

  80. Summary I hope you've seen that generics are a very useful tool that provide you with an extra layer of abstraction that can allow you to reuse code in new ways. In this module I talked about when to use generics and how to declare and use type parameters. They are the secret ingredient that lets you write your code to work with lots of different types. I covered the syntax for declaring and using generic functions, classes, and interfaces. The thing to keep in mind is that they're all just a slight variation of their non-generic versions. The last topic I covered was generic constraints and how constraining your generics to just a few types can actually free you to do more creative things in your generic implementations. In the next module, I'm going to explore some of the most useful TypeScript compiler options, and show you how to manage your TypeScript projects with a special file named tsconfig.json.

  81. Compiler Options and Project Configuration Introduction and Overview Welcome back. In this module I'm going to talk about TypeScript compiler options, and how you can use a special file named tsconfig.json to configure your TypeScript projects. I'm going to start by covering several different compiler options. There are lots of different options, and I'm only going to cover a few of the most common ones, but I will show you where you can find more information about all of the available options, so you can explore them on your own and know where to find help with them when you need it. I'll then cover how to create and use a tsconfig.json file to configure your TypeScript projects. They're very much related to compiler options, since most of what they contain are the options you want to use when your code is compiled to JavaScript. The other thing you can do with tsconfig files is specify which files should be included or excluded in the compilation process. We'll see how to do all of that.

  82. Specifying Compiler Options Before I talk about specific compiler options, I want to point out that there are lots of ways you might specify options when compiling your TypeScript code. You can obviously specify them on the command line by running the TypeScript compiler from a terminal. The compiler is named tsc, and I'll show you some examples of using it and passing options to it shortly. Depending on the editor or IDE you're using, there may be some sort of configuration pane or option screens that let you specify TypeScript options. These can be handy because you don't have to remember or look up all of the options and their syntax. Another option, and one you've seen me use in this course, is to specify the compiler options as part of a build task. Early in this course, I configured a Visual Studio Code build task and specified the options that should be passed to the tsc command inside it. You could do something similar with other build automation tools as well. Another option, which we'll explore in this module, is using a tsconfig file to specify how the files in your project should be compiled. I just want you to be aware that there are lots of ways to specify compiler options, and which option you choose will likely depend on the editor you use, and the build process you implement for your project. Let's now look at a few of the most commonly used compiler options. I spent a lot of time in an earlier course module discussing TypeScript modules. When you use modules in TypeScript, you also use the module compiler option and tell the compiler which module format it should output. You just add --module to the tsc command, and then specify the module format, such as CommonJS or AMD. There are other choices, and I'll show you how to find a list of them all in just a minute. The module option is one of the options that also has a shorthand version. Instead of typing --module, you can just type --m if you like. The --moduleResolution option lets you specify how the TypeScript compiler will attempt to resolve referenced modules. The two choices are node and classic. Specifying node will cause CommonJS modules to be resolved the same way they are in NodeJS. Specifying classic will resolve modules using the algorithm that was the default before TypeScript version 1.6. The --target option, which can be abbreviated with just the letter t, lets you specify which version of JavaScript should be output by the compiler. ES3 is currently the default, but it also supports ES5 and ES6, and I'm sure other options will be made available as soon as new versions of JavaScript are released. The --watch option, abbreviated with a w, lets you leave the compiler running in watch mode. This means that when changes are made to one of the source TypeScript files, the compiler will automatically compile it to JavaScript. For most of this course I've been using this option. The build task I started in Visual Studio Code runs the compiler with the watch option, which allows me to continually make changes and immediately run the resulting JavaScript without stopping to manually compile it. The --outDir option lets you specify a directory that should receive all of the compiled output files. This is handy for keeping the compiled JavaScript files neatly segregated from the TypeScript source files. noImplicitAny is an option that attempts to help you with your presumed goal of explicitly declaring types for your variables. If you use this option and the compiler infers that some variable will have the Any type, then you'll get a compiler error. Using it doesn't mean that you can't use the any type, but if you do, you'll need to do so explicitly. Okay, those are just a few commonly used compiler options. Let's now go take a closer look at compiler options in a demo.

  83. Demo: Using Compiler Options In this demo, I'm going to show you where to get more detail on all of the available compiler options, and show you how to run the compiler from the command line. I'm going to start here in a browser on the TypeScript GitHub repo. There's a page in the wiki that lists all of the compiler options. You can see the URL for this page here in my browser, but you can also just remember that it's part of the TypeScript repo and find it that way. I'll scroll down just a little bit to give you a sense of how many options there are, and how they're presented on this page. Options are specified using two dashes as a prefix. This page also tells you if there's a shorthand version of the option, and provides a short description for each one. Here you can see a couple of the options I discussed in the slides. The --module option can be abbreviated with just the letter m. The description gives you a few details about how to use it, along with a list of all the valid module formats. A little further down, you can see the --target option, along with its shorthand format and valid values. I'll keep scrolling just a bit, and you can see that there are lots of options here. I encourage you to skim the whole list yourself to see if there's something here that will help you generate JavaScript in exactly the format you need it. I will now go back to Visual Studio Code and open the task.json file inside the .vscode folder. I want to show you again the compiler options I've been using in this course, before showing you how to use the same options for the command line. I'm specifying a --target JavaScript version, an output directory, a module format, and I've told it I would like it to generate source maps and run in watch mode. I'll now go over to my terminal so I can compile the app from the command line. Before I do that, I want to show you one more option you have to discover the available compiler options and how to use them. The TypeScript compiler is named tsc. You can just type tsc --help to get a list of all available options. I'll scroll up a little, and you can see that the first thing output is the TypeScript version I'm using, as well as the syntax for running the compiler, and a couple of examples. Below that, you get a long list of all the available options, similar to the one I showed you on the TypeScript GitHub repo. Okay, let's now clear the screen and run the compiler here from the terminal. The first thing I'll do is delete everything from the js directory, which is where I want to send all of the output. This isn't required, I just want to make it clear I'm generating new output, and you're not seeing any old files left from the previous builds. The directory is now empty. I want to use the same options I specified in the Visual Studio Code build task. I'll type tsc followed by --target to specify the output JavaScript version. The target option can be abbreviated with the letter t, so I'll change it to just use that. I'll compile it to the ES5 version of JavaScript. I want all of the output files to be put in the js directory. I specified that with the outDir option. I'll use the shorthand form of the module option to specify I want to output my code in the CommonJS format. I'll then add --sourceMap to make sure it generates source map files, and then tell it to compile the app.ts file. Once that's done, I'll again list the contents of the js directory. Notice that there are lots of files listed here, even though I only told it to compile app.ts. That's because the compiler follows all of the module references and compiles all required files. Also notice that it output the source map files. They're the files with the .map extensions. There's also a lib directory in the output. That's because the output files are structured to match the source files. The LibraryManager project includes a lib folder that has one TypeScript file in it. The lib directory here was created to maintain that structure. If I list the contents of it, you can see that it contains the compiled version of the utilityFunctions.ts file from the lib folder of the project. The one compiler option I'm using in Visual Studio Code that I left off here is the watch option. I'll go back to the tsc command and add it to the end, just to show you how it behaves. When I run the compiler again with that option enabled, you can see that it compiles all of the files and tells me that it's watching for file changes. The process continues to run, and you can see that I didn't get a new command prompt here in my shell. If I were to go make changes to some of my source files now, they would automatically be compiled. I can stop the process here in the terminal by pressing Ctrl C. Let's now go talk about how to set up a tsconfig.json file.

  84. Role and Structure of tsconfig.json Support for tsconfig files was added in TypeScript version 1.5. I think they make management of TypeScript projects easier, but you're certainly not required to use them. They're simple json files that provide a few nice benefits, but first is that they mark the root of a TypeScript project. The settings you apply in a tsconfig.json file will apply to the TypeScript files in that directory, and all subdirectories by default. When you start the compiler with no input file specified, the compiler will look for a file named tsconfig.json in the current directory, and continue up the directory hierarchy until it finds one. If you do pass a source file to the compiler, then the tsconfig file will be ignored. They also give you a place to specify compiler options. You can then invoke the compiler with no options, and it will use the options listed in the tsconfig file. Any options you pass on the command line will override those in the config file. The tsconfig file is also the place to list the files you want included or excluded when the compiler runs. I'll show you how to do that on the next slide. The structure of a tsconfig.json file is pretty simple. It's just a json file, which is basically a set of key value pairs. Everything in the file goes inside a set of curly braces. The property you will probably use most is called "compilerOptions." Inside the curly braces for it, you define all of the options you want to use. Here I've set the target to "ES5" and specified that the compiled output should be placed in the "js" directory. I could continue to list as many options as I needed here. You use the "files" property to list the files you want passed to the compiler. Notice that this property is just an array, and the file names are just strings in the array. The "files" property lists the files you want to include, however, if it's easier to list the files you want to exclude, then you can use the "exclude" property instead. If you've installed some packages with NPM, you probably don't want the compiler trying to compile the files in the node_modules directory, and this is an easy way to avoid that. It's important to note that the "files" property and the "exclude" property are mutually exclusive. If you do include both in a tsconfig file, then the "files" property will be used, and the "exclude" property will be ignored. Let's now go add a tsconfig.json file to the LibraryManager project.

  85. Demo: Managing a Project with tsconfig.json In this demo, I'm going to add a tsconfig file to the LibraryManager project, and use it specify the compiler options and the files I want to compile. I'll start here in Visual Studio Code and add the new file to the root of the project. Everything in the file needs to go inside a pair of curly braces. If I type Ctrl in Visual Studio Code, I get a list of the valid properties I can add to the file. I'll start with the compilerOptions. I'm going to use some of the same options I've been using throughout the course. I'll start to type target, and notice that I'm also getting code completion help on the compilerOptions. This is another nice way to explore the available options. I'm going to target es5. I'll then direct the output to the js directory, and specify that I want to use the CommonJS module format. So far I've been using the source map option to tell the compiler to generate source map files. I'm going to set that property to false here, so that we can see an obvious difference in how the compilation is being performed. Okay, I'll now jump over to my terminal. Before running the compiler, I'll quickly show you the current contents of the js directory. It's got all of the JavaScript and source map files form the last time I ran the compiler. I'll now delete all of that and make sure the directory is empty. Alright, I'm now ready to run the compiler. Since I now have a tsconfig.json file in place, I can start the compiler with no options at all, and it will use those I added to the file. If I now list the contents of the js directory, we can see that we have JavaScript files, but we no longer have the source map files, since I set that property to false in the tsconfig file. I'll now go add the "files" property to the tsconfig file, and just add the "shelf.ts" file to the array. This instructs the compiler to only compile that file and any files it depends on. The shelf file currently doesn't have any dependencies. I'll go back to the terminal and delete the contents of the js directory again. I'll type tsc to run the compiler. We can see that the output directory now only has one JavaScript file. I'm now going to change the file it should compile to be app.ts. It imports lots of other modules, and I want to demonstrate once again how the compiler follows those imports and compiles all of the required files. I'll run the compiler again, and once more list the contents of the js directory. This time we see app.js, as well as all of the JavaScript files it depends on. If, for some reason, you didn't want the compiler to compile all of those dependencies, there is an option called noResolve that will prevent it from done that. The compiler is using the tsconfig file I created because the file was in the same directory I'm in when I'm starting the compiler, however, you can explicitly direct the compiler to a tsconfig file in another directory using the --project option. This is the command I would type if I wanted to use the tsconfig file inside the lib directory. Okay, I now want to show you how to use a tsconfig file in conjunction with a Visual Studio Code build task. I'll again delete the contents of the js directory. The configuration for the build task I've been using in this course is stored in the task.json file in the .vscode folder. You can see that I'm specifying compiler options inside the "args" array. As we just saw in the terminal, the compiler will use the tsconfig file when it's invoked with no options on the command line. I can effectively accomplish the same thing in this build task by specifying an empty array for the "args" property. I'll now use the command palette to start the build task. If I now look inside the js folder, I see JavaScript files, but no source map files, so I know the build task read and used my tsconfig.json file.

  86. Summary The TypeScript compiler has matured over time, and now offers lots of options you can use to make sure you get the precise JavaScript output you need for your project. In this module, we looked at a few of those options, but I also showed you several places you can review the list of available options and discover the ones that may be helpful to you. We also saw the benefits of using a tsconfig.json file to both specify compiler options, as well as the files you want to include or exclude from a compilation. I highly recommend you use tsconfig files with your projects. They're simple to set up, and give you a single place to control how your project will be compiled. In the next module, I'm going to show you how to create and use type definition files. They can make your TypeScript development experience much nicer, by making it easier to work with external libraries in TypeScript.

  87. Type Definitions Introduction and Overview Hello, and welcome back. In this final module of the course, I'm going to talk about type definitions. In case you haven't noticed, there is a lot of JavaScript out in the world. Type definitions let you take advantage of all that code and easily incorporate JavaScript libraries into your TypeScript projects. I'll start by talking about the role type definitions play in TypeScript development, and then present DefinitelyTyped, which is a huge repository of type definition files for just about any JavaScript library you can imagine. Type definition files can be downloaded directly from the DefinitelyTyped GitHub repo, and a couple of tools have been developed to make obtaining and managing them a little easier. I'll first show you the basics of working with the tsd type definition manager, and then we'll take a look at a newer tool named typings. Let's get started by talking about exactly what type definition files are.

  88. What Are Type Definition Files? Type definition files are files you add to your project that contain type information for a library you intend to use. They contain no implementation details, and mainly consist of interfaces that make it possible for the TypeScript compiler to type-check your code against the library you're using. They're primarily used as a TypeScript wrapper around JavaScript libraries, although they can be helpful for TypeScript code as well. They provide structure and strong type-checking for lots of popular JavaScript libraries and frameworks. Since they contain no implementation, their primary benefit is as a design-time tool for type-checking and editor support. The type-checking helps you find errors before they make it to production, and a TypeScript-aware editor will provide nice code completion support for the library, making it easier for you to find the properties and methods you need on an object, as well as the number and type of parameters expected by a function. The files are easy to spot in a project. They all end with a .d.ts file extension. There are a number of sources you can use to find the type definition files you need. One thing to keep in mind when you're looking for one is that many times the type definition file for a library is developed completely independent of the library itself. The person or people that put together the type definitions may not be involved with the original library at all. I think this is generally not a problem, but I want to point it out only to make it clear that there can be cases where the type definition file may be out-of-sync with the version of the library you've chosen. Easily the largest source of type definition files is the DefinitelyTyped repository on GitHub. There are currently well over 1500 libraries represented there. This is where you'll get most of the files you need. There's a relatively new tool available that allows you to install type definitions from other sources including GitHub, Bitbucket, and npm. It's called Typings, and we'll take a closer look at it later in this module. TypeScript now has support for type definition files included in npm packages. This is actually how I prefer to get type definition files. Since I'm already using npm to install JavaScript libraries, it's great when the author of the library has already included the definition file I need to use the library from TypeScript. However, this is a relatively new feature of TypeScript, and very few npm package authors currently include definition files with their packages. I hope that changes over time. Another option is to write your own type definition files. If you write your own for a new library, you can even send a forward request to the DefinitelyTyped repo to have your file included there for others to use. You can also use the TypeScript compiler to generate type definition files from TypeScript source files. I'm not going to cover writing your own type definition files in this course since it's a bit of an advanced topic and not something most people will have a need to do.

  89. Ambient Modules Before I go any further, I want to briefly discuss ambient modules. Large JavaScript libraries could potentially have lots of modules in them. Since modules in TypeScript are files with top-level export statements, each module in a large library would have to get its own d.ts file, and that would quickly become unwieldy and inconvenient. The solution is to declare ambient modules inside a single d.ts file. In this example, imagine that I have a file named cardCatalog.d.ts. I use the declare keyword to declare a new ambient module named "CardCatalog." Within that module, I can export the things I want to expose as part of the module API. Ambient modules don't provide any implementation details. In the case of type definition files, they're just the wrapper around an implementation that's defined in the actual library. Using the ambient modules defined in a type definition file is a little different from using a normal module. Since there aren't any top-level exports, it can't be imported directly. I first need to add a triple-slash reference to the d.ts file. After that, I can write an import statement, but I don't specify a file path for the module to import, I just type the name of the module in double quotes, exactly as it was defined in the d.ts file. You might imagine that the list of triple-slash references could grow pretty long inside any given file, but we'll see how that can be greatly minimized, or even eliminated, in the upcoming demos.

  90. DefinitelyTyped Before I jump into a demo and show you how to get started using type definition files, I want to talk a little more about DefinitelyTyped. As I've already mentioned, it's a huge repository of type definitions. They all exist in a single GitHub repo, but there are actually several ways you can download and add them to your project. The first option is to find the file that you want in the GitHub repo and download it directly from there. This is the simplest option, but may prove cumbersome if you need lots of files. If you're a Visual Studio user, you can use the NuGet package manager to install type definitions that are housed in DefinitelyTyped. Almost all definition files are represented as a NuGet package. Just search for DefinitelyTyped inside NuGet to see a list. tsd is a type definition manager developed specifically to work with DefinitelyTyped. I'll talk more about it in a few minutes. Typings is a type definition manager capable of working with multiple sources, and DefinitelyTyped is one of them. I'll also talk more about the typings manager a little later. Let's now go see how to download and use a type definition file directly from the DefinitelyTyped repository.

  91. Demo: Using Definitions from DefinitelyTyped In this demo, I'm going to show you the DefinitelyTyped repository and then download the type definitions for a popular JavaScript library named lodash, and show you how to use it in TypeScript. Before you bother installing type definitions, you need to make sure you've installed the library the definitions are meant to make available to TypeScript. I'm going to install a JavaScript library named lodash. It's a very nice utility library with lots of useful functions. I'm going to install it in the LibraryManager project with npm, which I'll do here in my terminal. The first thing I need to do is create a package.json file to hold references to all of my installed npm packages. I'll use the npm init command with the force option, just so I don't have to answer a bunch of questions about it right now. I can now install lodash with the command npm install lodash --save. That just takes a couple of seconds to download. I'll now go back over to Visual Studio Code, and you can see that I have a node_modules folder in my project. Inside it, you can see that there's a folder for lodash. Lodash is a pure JavaScript library, no TypeScript, and it also doesn't include a type definition file in the npm package, which is why I'll now head over to the DefinitelyTyped repository on GitHub. The repository is pretty easy to find if you just search for DefinitelyTyped, but you can see the URL for it here in my browser. I'll scroll down just a bit to give you a sense for how many libraries are represented here. It's a long list. In fact, it's so long, I think I'll just search the page for lodash. Okay, here's the one I want. Inside the lodash folder there are several files. The one I want right now is the main definition file named lodash.d.ts. Once it's open, I'll click the Raw button and then select and copy all of the code in it. Back in Visual Studio Code, I'll add a new file to the project named lodash.d.ts, and then paste in the code. After pasting the code, I'm here at the end of the file. Notice that the last thing in the file is an ambient module declaration. It declares a module named "lodash" and just exports the underscore, the low dash, which is defined earlier in the file. Now that I've got the file and I know the name of the module I need to import, I can go over to app.ts and start to use it. Remember that before I can import from an ambient module I need to add a reference to the file containing the module. I'll use the ref code snippet in Visual Studio Code to paste that in for me. The file I want to reference is lodash.d.ts. I can now import from the module. I'll import everything, and specify that I'll refer to it with the conventional lodash character, and then I'll list the name of the ambient module in quotes. I'm now ready to start calling functions in the library. I'll come down a couple of lines and write some code that changes the casing of a book title as a quick example. I'll declare a new variable named snakeCaseTitle, and assign it the return value of a lodash function. Notice that when I type the dot after the underscore, I'm now getting code completion help. I've got a huge list of all of the functions available in lodash. It's also telling me the expected types for parameters and return values. I'm going to call a function named snakeCase, which you can see takes a string as a parameter, and returns a string. I'll give it a string to convert, and then log the result. I'll start the build task, and then press F5 to run the code. You can see in the console that it converted my string to snake casing, which seems to convert the words to lowercase and then replace the spaces with underscores. That's probably not particularly useful for book titles, but maybe for other things. Okay, so that's the basics of using a type definition file. Let me quickly recap. I decided I needed to use a JavaScript library in my TypeScript project, so I first went and downloaded the library. Don't forget this step. I'm a little embarrassed to admit it, but I once got so focused on TypeScript that when I decided I needed a JavaScript library, I quickly grabbed the type definition file for it, and then spent 10 minutes trying to figure out why my code didn't work. It turned out that I never actually added the library to my project. The type definitions are just a wrapper around the actual library, so make sure you have the library first. Once you have it and the type definitions in place, you can import what you need from it, and then use it as if it were actually written in TypeScript. Let's now go see how to use tsd to add type definitions to a project.

  92. Managing Type Definitions with tsd Now that we've seen how you can go directly to the DefinitelyTyped repository and get type definition files, let's talk about using tsd to manage those files instead. tsd is a command line tool that helps you find and download type definition files. It works exclusively with the type definitions in the DefinitelyTyped repository. When you use it to install type definitions, it adds a new file to your project named tsd.json, that stores a reference to the file you installed. Another nice feature it offers is storing triple-slash references to all of your installed type definitions in a single file for you. You can then just reference that single file instead of every file you need individually. You can do the same thing manually if you decided not to use tsd, but it just automates the creation of that single reference file for you. So all of these are nice features, but tsd has been deprecated. This was announced in early 2016, and the plan is that the typings tool we'll look at shortly, will replace tsd. However, tsd is still in widespread use and I expect will still be around for a while, so I wanted to make sure I covered it in case you are either already using it in some capacity or inherit a project on which it's used. Let's go see how we could have added type definitions for lodash to the LibraryManager app using tsd.

  93. Demo: Installing Type Definitions with tsd In this demo, I'm going to use tsd to install the same lodash definition file I used in the last demo, and show you the files it creates in the project. The first thing I'm going to do is delete the lodash.d.ts file I added in the last demo, since I'm now going to use tsd to install it. I'll leave the lodash library installed in the node_modules folder since I'm only changing how the type definitions for it are installed. Before I do the installation, I want to quickly show you the tsd website. As you can see in the URL, it's a part of the DefinitelyTyped website. You install tsd with npm, and you can see the command to do that right here at the top of the page. I'll click on the Readme link, and it takes me over to the GitHub repo. From there you can find some of the commands you can execute with it, and the syntax to search for and install definition files. I'm going to keep things pretty simple and just install the definitions for lodash. To do that, I'll go back to my terminal and type the command, tsd install lodash --save. That will install the definition file, and save a reference to it in a new file named tsd.json. I'll go back to Visual Studio Code, and we can see that the new tsd.json file appears in the project window. It contains some basic information about the definitions I have installed, including the specific commit from the DefinitelyTyped repository I used. In addition to the tsd.json file, I also have a new folder in the project named typings. I'll expand it, and you can see that it currently has one subfolder named lodash. Inside it is the same lodash.d.ts file I installed in the last demo. Here at the end of the file, you can see the same ambient module declaration I showed you before. The typings folder also has another file named tsd.d.ts, which the tsd command created to store references to all of the definition files you install with it. I obviously only have one reference in it right now, but as I install more, tsd will add the proper triple-slash references to them here. I can then just reference this single file instead of each file individually. Let's go do that now. I'll open app.ts and change the file in the reference at the top to be the tsd.d.ts file inside the typings folder. That's the only update I need to make. I can leave my earlier import statement exactly as it is. I'll come down a couple of lines and type _. just to show you that the code completion support still works. Let's now go talk about the typings tool that's the designated replacement for tsd.

  94. Managing Type Definitions with typings The typings tool is conceptually similar to the tsd tool, but has some additional features. Just like tsd, it lets you find and download type definition files, however, unlike tsd it can install files from multiple sources. It can use the DefinitelyTyped repository, but it can also use GitHub, Bitbucket, and npm as sources. It also manages references to your installed definitions, and stores "triple-slash" references in a single file. But it's new, and not yet widely adopted. As I record this in early 2016, it seems that the story around managing type definition files is changing rapidly, so I would encourage you to check in on both the tsd and typings projects regularly if you decide to use one of them to manage your definition files. Let's now go see how to install the lodash type definitions with the typings tool.

  95. Demo: Installing Type Definitions with typings In this demo, I'm again going to install the type definition file for lodash, but this time I'm going to do it with the typings tool. I hope that installing the same file in several different ways highlights the differences in each approach. Before I get started, I want to delete from the project the files installed by tsd in the last demo. I'll delete the entire typings folder, as well as the tsd.json file. Okay, I'll now jump over to my browser and give you a quick peek at the typings GitHub repository. You can see the URL for it here at the top. I'll scroll down a little, and you can see that it has a nice Quick Start section. The most important piece here is how to use npm to install typings. It also lists some of the basic commands and their syntax. A little further down are some notes and tips on moving from tsd to typings. You can use it very much like tsd. It's a command line tool, and since I already have it installed, I can just type typings install lodash --ambient --save. The ambient option tells typings that it should use DefinitelyTyped as the source. The --save option operates much like the --save option for tsd. It will store reference to the installed file in a separate file in my project. That just takes a second to install, and I can now go back to Visual Studio Code and see what it added. Rather than adding a file named tsd.json to the root of my project like tsd, typings added a file named typings.json. It just contains a reference to lodash and the source typings used to download it. Just like tsd, the typings tool also added a folder to my project named typings. However, the contents are a little different. There are separate reference files in folders named browser and main. Browser would be used for client-side apps, and main would be used for node apps. The contents of the two could be different based on how the typings definition was created by the author of the file, but since lodash was just downloaded from DefinitelyTyped, the two files are essentially identical. You can see that the main.d.ts file references the lodash.d.ts file inside the main folder. If I installed other definitions, they would be referenced here as well, allowing me to reference this single file just like I did the tsd.d.ts file when I installed definitions with tsd. I'll now open app.ts and update the reference at the top to point to the new main.d.ts file. I'll come down again and type the underscore that represents the lodash library, and you can see that my code completion support is still working as expected. Before I end this demo, I want to show you one more trick that will allow you to get rid of even the single triple-slash reference I'm using at the top of this file. In the previous module of the course, I showed you how you can use a tsconfig.json file to configure your TypeScript projects and specify the files that it should include. If I add the main.d.ts file to the tsconfig.json file, the compiler will read that, and I don't need to include it in every file. To show you that, I'll first delete the reference at the top of this file. You can see that I immediately get an error in the code trying to import the lodash module. I'll then open my tsconfig file and add main.d.ts to the "files" section. I'll go back to app.ts, and you can see that the error is now gone and I'm still getting code completion support for lodash. I have seen cases where Visual Studio Code didn't immediately recognize a change like that to the tsconfig file. If that happens to you, just reload the window, and it should pick up the change. I want to be clear that adding main.d.ts to the file section on the tsconfig file was not specific to the typings tool. You can do the same things with the tsd.d.ts file generated by tsd, or your own file you create to maintain a list of references.

  96. Summary Type definition files are very helpful. I hope you've seen the benefits they can provide to your TypeScript projects in this module. There's a ton of useful JavaScript code out in the world, and definition files let you bring them into your projects, provide type-checking for them, and give you great editor support to help you write better code faster. The DefinitelyTyped GitHub repo is an invaluable source of type definition files. We looked at it in this module, and I showed you how you can manually get the files you need. I also gave you a quick overview of a couple of tools that are available to help you manage the type definitions in your projects. The tsd and typings command line tools can help you download and maintain references to the type definitions you need. That brings us to the end of the course. I hope you've enjoyed it. I'm obviously a huge fan of TypeScript, and I've had a lot of fun putting this course together. I hope you're now prepared and eager to start building your own TypeScript apps. Thanks for watching. Go write some code.