What do you want to learn?
Leverged
jhuang@tampa.cgsinc.com
Skip to main content
Pluralsight uses cookies.Learn more about your privacy
TypeScript Fundamentals
by John Papa and Dan Wahlin
TypeScript Fundamentals walks you through the key concepts and features that you need to know to get started with TypeScript, and use it to build large (and small) scale JavaScript applications. Updated March 25, 2016 for TypeScript 1.8.
Resume CourseBookmarkAdd to Channel
Table of contents
Description
Transcript
Exercise files
Discussion
Learning Check
Recommended
Getting Started with TypeScript
Course Introduction
Welcome to the TypeScript Fundamentals course. In this course, we're going to walk you through the key concepts and features that you need to know to get started with TypeScript, and use it to build large and small scale JavaScript applications. My name's Dan Wahlin, and you can reach me on Twitter @danwahlin, or at my blog, which is located at weblogs.asp.net/dwahlin. And my name's John Papa, and you can catch me on Twitter @john_papa, or you can catch my blog at johnpapa.net. In the first module, we're going to introduce the overall concept of TypeScript and what it brings to the table. What does it offer you as a JavaScript developer? We'll cover some of the key features, as well as some of the different tools you can use to build TypeScript and actually convert it into JavaScript code. In module two, we're going to dive into looking at the differences between dynamically and statically-typed languages, and take a look at how we can use different types, like Booleans and strings and numbers to define things like functions and objects of all sorts of variables. Once we cover some of the different variables in the type system within the TypeScript language, we'll also then talk about classes and how we can actually organize our members and make them all play together and play together nicely. We'll then talk about interfaces and introduce the concept of what an interface is, and how we can use it to drive consistency in our code. And to build on the concept of separation or organizing your code, in module four, we'll talk about what modules are in TypeScript, and how they emit different kinds of modules in JavaScript, what the difference is between an internal and an external module, how you can import and export modules, and then also how you can use these with dependency resolution and features like AMD, asynchronous module definition. By the end of the course, you'll have a solid understanding of TypeScript. So let's go ahead and jump in.
Introduction
In this module, I'm going to introduce you to some of the key concepts that you need to know to help get you started using TypeScript to build enterprise-scale JavaScript applications. Now before jumping into the features and all the cool stuff it offers, I'm going to address the all-important question of why would I want to use TypeScript versus writing custom JavaScript? That's a great question. It's a question I've asked, John's asked it, John and I have talked about it, and I know many others have asked it out there in forums and other areas on the web. So I'll try to address that as we get started here, very first thing. Once we go through that, we're going to talk about some of the different features that TypeScript offers. We'll talk about the tooling story and some of the other frameworks you can use it with, and then I'll build a simple hello world-type example to help kick things off, and get you thinking about the type of language and the code that you're going to write that ultimately, you're going to see, will generate our JavaScript. So let's go ahead and jump in and get started with the all-important question of why would I want to use TypeScript over using just regular JavaScript?
Why use TypeScript?
In this section, we're going to talk about some of the different challenges that we encounter as JavaScript developers, especially on enterprise-scale type of JavaScript apps, and this will help us address the question of why would I want to use TypeScript versus writing custom JavaScript? It's a great question that a lot of people have asked. So one of the things that, if you've written a lot of JavaScript applications, you probably found is that JavaScript can tend to feel this way. If you don't follow some of the patterns out there, such as the revealing module pattern, the revealing prototype pattern or others, then it tends to feel a little bit messy. I call it function spaghetti code. And as a result, the messiness leads to a lack of maintainability, lack of reuse if you don't do it right. Now certainly you can write clean JavaScript, but you're going to have to follow some patterns to do that, and I have a whole course on that on Pluralsight if you're interested called "Structuring JavaScript Code". But really what we're after is we want something that feels more like this. We want something that's very maintainable and easy to work with, and that's one of the things that TypeScript can really do. It can really clean up the application. Now you might say, "Yeah, but my app only has "maybe a few hundred lines, "or maybe even a thousand lines of JavaScript." Well, I'm not here to say that TypeScript is the only way to go. This course is simply about how to use TypeScript, so I'll leave it up to you to make the decision if it's appropriate or not. I think that on larger-scale apps, more enterprise-scale though, that TypeScript can definitely fill a needed area, and that is making our code more maintainable, and we'll talk about that throughout the course as we proceed here. Now one of the things that we encounter as JavaScript developers is we write this functions spaghetti code, but really what we're after is more modular code. And John likes to call it ravioli code. So function spaghetti code is what most JavaScript developers do, at least when they first start out. Maybe they learn some patterns, then they make it into more ravioli code after learning some of these different patterns that are out there, but it definitely takes some additional effort to write more modular JavaScript code, and little bit more learning is involved there. So that's definitely a challenge that can be overcome, but nonetheless, a challenge we encounter. Now another thing that kind of has pros and cons is JavaScript is a dynamically type system. And what that means is in the good area here, variables can hold any object. It could be a Boolean, it could be a string, a number, a object literal, and those types of things. And that's awesome because it's very flexible, and definitely something that I personally like a lot about JavaScript, but the downside of that is when you get to larger-scale apps, now, if you don't have tests to back up what you're passing or assigning to variables or passing as parameters to functions, then things start to get a little bit challenging there. So the good part of this though is that yes, JavaScript is a dynamically typed language, and that's very nice to have. Types are determined on the fly, and we get the implicit type coercion or conversion, if you will, from, for instance, string to number, if you had the number one in quotes, and you want to do a comparison in an if statement to the literal number one, then it'll automatically try to convert the string into a number in order to do that comparison accurately. Now that's good and bad, though. Because sometimes we don't want that. So the bad is, it is difficult to ensure, especially in large-scale apps that proper types are being passed. Now you can do that by writing unit tests or you can just say, "Hey, we're going to be really careful, "but you know how that goes, especially in large teams." Really the only answer there is to have tests to back up, that the proper data types are being passed around. Now another solution in JavaScript that not a lot of developers tend to use, at least from the ones I interact with, is the triple equals. And this is a way to tell JavaScript don't coerce a type or convert a type, for instance between a string number one into the raw number one. Just treat it as a string versus a number, therefore they will never be equal. And so you can always do that, but again, not everybody does that, so this is yet another challenge. And then when you have enterprise-scale apps, often times you'll have thousands and thousands of lines of code. I've been involved in several apps that are of this type of scale that are very, very heavy on the JavaScript side, and it does tend to be a little bit challenging to make sure that your types are being passed appropriately, that a string is being passed or a number, when that's what's supposed to be passed behind the scenes. So that's yet another challenge that we encounter in JavaScript. Once again, something that we can overcome, but nonetheless a challenge. Another challenge that can come up is as developers move from pure server-side or desktop-type coding, they find themselves having to learn JavaScript and that's kind of how we get into the messy code situation that I introduced this section with. They might be coming from Java or .Net, maybe it's PHP or Ruby on Rails, or something like that. And if that's all they've done, then learning JavaScript and all the things that go with it, such as the DOM and the web in general, definitely is challenging, and that's an area where TypeScript you'll see, can actually kind of step in and help quite a bit with. Now I don't think that's a justification for not learning JavaScript in my personal opinion. I think it's very important that everybody learns JavaScript, so they know the core language. But this is an area you'll see throughout this course, where TypeScript could certainly help out. Now there's a lot of different frameworks and languages out there that are trying to meet some of these challenges I've been discussing in this section, such as encapsulation, messy code, the type system, and so on and so forth, and some of these have been around for a while. Others are pretty new, as well. Now TypeScript is certainly not the only game in town, though. Now we can always write pure JavaScript, of course, and I recommend that, if that's what your app needs. And if you can maintain it well, then I'd say go for it. But CoffeeScript is another alternative. Google has DART, which is yet another alternative for generating JavaScript, so you write one language, CoffeeScript or DART, and then it outputs JavaScript for you. Or, of course, you could use TypeScript. Now TypeScript itself you're going to see really is JavaScript. It's just a superset of JavaScript. But a lot of people, though these different languages and frameworks do satisfy some of these challenges I've been talking about, I've heard a lot of people complain that why would I want another layer that generates JavaScript? And you know, if your application isn't that big, and you can just write pure JavaScript and make it maintainable and reusable and take variables and functions out of the global scope and things like that, then I'd say go for it. The discussion here in this section is not to convince anyone that TypeScript is the only way to go. The goal here is to show some of the holes or challenges we have as JavaScript developers that TypeScript can certainly help out with. Now when it does come though to generating code or having this extra layer above our JavaScript, I actually think that's a little bit of an invalid argument because most of us use a language that sits above another language. So a good example of this would be if we're writing Java, or we're writing .Net, then really all we're doing is writing a level above C or C++, and then that, of course, is a level above things like assembly language, and there's a few in between there, but, you know, we really don't want to be going all the way down to machine-level code. Assembly code, yeah, well, I don't want to do it (chuckles) so, we have these other languages that are layers on layers on layers. TypeScript really is the same type of analogy here. It is a layer, a language that you can use that generates JavaScript. And yes, it does introduce a different way of doing things, but is it unique? No, I think that time has proven that different languages are doing the exact same thing we're talking about here, because that's exactly what Java, .Net, C, C++, and these other languages do. So now that we've talked about some of the different kind of holes or challenges that JavaScript presents to us, and we've talked about some alternatives and sort of the need to have a way to get encapsulation and be able to make sure our types are appropriate, and things of that nature. Let's go ahead now and officially jump into, So what is TypeScript and what are some of the features it offers?
TypeScript Features
TypeScript has several different features that'll appeal to enterprise-scale JavaScript developers, and really, any JavaScript developer looking for modularity, encapsulation of code, and some of the other features I'll talk about in this section. So what I'm going to do is introduce what TypeScript is, talk about some of the features that it offers us, as developers, and then we'll talk about the compilation process, and wrap up with a quick peek at what TypeScript code actually looks like, and what it generates as far as JavaScript goes. So let's start off by talking about what is TypeScript, exactly? Well, if you head over to typescriptlang.org, the website for TypeScript, you'll find this type of definition here. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Now what's really interesting about this is that it is infers and infers correctly that TypeScript is not a totally separate language from Javascript. It's actually built on top of JavaScript. That's why they say it's a superset. But that's actually very interesting because TypeScript, although it does add some really nice features and some keywords that you won't find in JavaScript, you can actually take raw JavaScript code, paste it into a TypeScript file, which you'll see has a dot TS extension, and it will just output that JavaScript. Now of course you wouldn't do that if you didn't use some of the features I'll be talking about here wouldn't make much sense. You'd just write normal JavaScript, of course. But this means I can combine these cool features I'm going to talk about here with just regular JavaScript if I want, and they'll both work really nicely together. Now let's talk real quick about some of the different options that TypeScript offers us. First off, it is designed to work with any browser, so the JavaScript is cross-browser compatible, it'll work in Internet Explorer, Opera, Chrome, Safari, FireFox, and all the different browsers out there. Because it is JavaScript, it'll work on any host, including using things like Node.js, which is very interesting, and we'll talk about that coming up a little later. Any OS can use TypeScript. It's open source, so I really like this because if you would like to see exactly what they're doing and how it's working, or actually contribute, it is an open source project that's hosted. And it has very good tool support. Now this is where I really think TypeScript stands above some of the alternatives out there. And that's because if you can catch errors between types that are being passed or in the structure of your code up front, then obviously it's easier to fix those versus getting way down the road or even having the app out in development, and testing it there. So the tooling support's actually a pretty big deal, and I would say this is a kind of critical piece of TypeScript because not only does it work, you'll see, with things like Visual Studio, from Microsoft, but it'll also work with a lot of other tools. One of those being, for instance, Sublime that works not only on Windows, but also on Macs and others. So very good tooling support, and we'll talk more about that. Now some of the key features that TypeScript offers are shown here. First off, as I mentioned earlier, TypeScript is a superset of JavaScript. Therefore, it supports standard JavaScript code. You don't have to actually rewrite everything in the TypeScript format if you don't want. Now what I like about this is I've already had some code that's in JavaScript, but I want to write some new pieces in TypeScript, I could actually work with both at the same time, and they'll still be compatible. Now I find that pretty compelling, actually. In addition to that, we have static typing. It's a lot easier if we can catch incorrect data types being passed up front, either through the tooling or through the compilation process. Then it is after the fact. In fact, a lot of the times when you do it after the fact during the testing phase, it's quite possible you might actually miss something that's being passed incorrectly, as far as the data type. We also get encapsulation. Now this is probably one of the most critical pieces. In addition to the static typing, I would say, and that's because we can actually write classes, and then we can even do naming containers, which they call modules. Now if you come from a Java, .Net, C++ type of background, this will probably be pretty attractive to you because you can apply the same skills that you have in those languages to TypeScript, and then it'll just automatically output the appropriate JavaScript to match with that. In addition to that, once you have a class, you can define things like constructors, you an define variables and properties, you can type those, as I mentioned. You can also define functions. Pretty standard things that you'd expect in any standard programming language out there. We also have support for interfaces. Now this opens up kind of an interesting possibility here. While JavaScript does not support interfaces natively, wouldn't it be nice that if we expect an object literal to be passed into a function, and we expected to have first name and last name, and if somebody doesn't pass first name and last name, we could catch that? That would be pretty nice. But we can actually define interfaces that say the minimum members that a particular type must have, and then if that rule's broken, our tooling or our compiler in TypeScript can catch that. And that's a pretty compelling option for TypeScript. We also have support for what they call arrow functions. This is another ECMAScript 6 type of thing that'll be coming out. But this is supported directly in TypeScript. Now if you have a C# type of background, you might be more familiar with the term lambdas. Very, very helpful for writing anonymous functions for things like callbacks, and it's used in some other areas as well in TypeScript. And then finally, if you're using an editor that fully supports TypeScript, you can get things like Intellisense, syntax checking, where if you pass an incorrect type, for instance if you pass a string, but it should have been a number, then it can underline it in red, and you can instantly know that you have some type of a problem in your code. So this certainly isn't all the features of TypeScript, but this kind of highlights the major features and it's a pretty compelling set of features, I think, because some of this, you just plain can't do in normal JavaScript, but yet this will output once you run it through the compiler, regular, normal JavaScript. Now let's talk a little bit about the TypeScript compiler. So what you do is you'll write TypeScript, and you'll write these using a dot TS extension for your files, and then from there, you'll run it through this TypeScript compiler, TSC, and you'll simply pass at the path to your TypeScript file. Now this would be if your tooling doesn't support the compilation process directly. For instance, in Visual Studio, you can actually just hit save on a TS file, and it'll automatically update a dot JS file behind the scenes for you, so it makes it really, really easy. But even with tools that don't support TypeScript directly, you can run this command line type tool, and compile it, and all that's going to do is output standard JavaScript. Makes it very easy to work with, and you don't have to be a master of patterns or whatever it may be to satisfy all of these features I just talked about. Yet, it'll work in all the different browsers out there. Now let's take a real quick look at what it looks like before we wrap up this section. So TypeScript itself looks a lot like what you might see in an object-oriented language. You'll notice here that I have a class called greeter. We have a variable up here called greeting, which is a type, so you can see that we have static type support. I have support for defining constructors. In this case, I can pass in a message that is a string, assign that up to my greeting, and then I have a simple function called greet, which returns hello and whatever the greeting is. Now that's a real simple example, but that shows some of the modularity in the encapsulation that we get with TypeScript. Now what this will output is just standard JavaScript. So we'll get a greeter object. Notice that then has this wrapper function around the contents, that function is self-invoked, and then inside of here, we have the constructor. Notice it takes the message and assigns it to a greeting. And then we use the prototype to extend our greeter and add a greet function. And it simply returns hello and the greeting. Now this is actually what would be generated once we run the TS file, the TypeScript file here on the left through the TSC compiler. Now what's nice about this is just right off the bat, we can see we get encapsulation and we get static typing. Just those two features alone, if you're writing a more enterprise-scale app, those are pretty big deals. And that's because we can catch a lot of errors up front before we get too far in our program, either through the tooling showing us with maybe some red lines, or through the compiler generating errors, if we're passing things incorrectly.
TypeScript Syntax, Keywords, and Code Hierarchy
Writing code using TypeScript is actually fairly straightforward if you already have a background in JavaScript, or even a C-based language. Now if you don't, it's still pretty easy to pick up, I think, but we are going to be using a lot of the same concepts that you'll find in JavaScript such as brackets, and even a lot of the keywords, because as mentioned, TypeScript is a superset of JavaScript. So what we're going to do in this section is talk about the basic syntax. I'll go through that pretty quickly. Then we're going to jump into some of the different keywords you'll encounter in the TypeScript language. And then we'll wrap up with just a real high-level look at how code in TypeScript is organized. So let's get started by taking a look at the syntax. So because TypeScript is a superset of JavaScript, the things you know now still apply as you write TypeScript codes. So for example, we're still going to use squiggly brackets as we start and end our blocks of code. So as we write TypeScript classes for instance, although those are new from the standpoint of ECMAScript 5 or earlier since those aren't in JavaScript, you're still going to use the same type of code that you'd write in JavaScript. You're going to end your statements with semicolons. And then the normal stuff you do in JavaScript such as for loops or if statements for conditionals or switches, all that type of stuff can be used directly because after all, it's just a superset of JavaScript. So all those JavaScript concepts still apply, which makes it really easy to get started if you already have a background in JavaScript. Heres a look at some of the important keywords and operators you'll encounter as you're building TypeScript code, and we'll be covering these as we go throughout the modules of this course. So first off, TypeScript supports the encapsulation concept of a class, and so there's a class keyword that you won't find in ECMAScript 5 or earlier, but you will find in TypeScript. You can also define the initialization constructor using the constructor keyword. We can work with modules in TypeScript, so we'll see down here that we have module as a keyword. And then modules can export different members out of the module. As we're working with classes in TypeScript, we can extend a class, so we can do inheritance, we can work with interfaces, which drive code consistency. We'll cover that more in a later module. And we can do that using the implements keyword. And then when it comes to modules, we can actually import modules using the imports keyword here. In addition to classes, we can also define interfaces for the code consistency across classes or across types. And then we can even control the visibility of members of a class by using public or private visibility modifiers. Now in addition to the keywords, we also have some operators you'll see. If you ever see a triple dot, that's called a rest parameter. And I'll cover this a little bit later in a future module in this course, but that's something that allows you to pass a comma-separated list of objects or items. You'll also see what we call the arrow syntax. Now this is used in a couple different areas. You can use it for, for instance, a callback function if you had an async operation to shorten it up. And you can also use it as you're defining functions and different members in interfaces to actually say, for instance, what the return type is of a function. TypeScript also supports the concept of casting, and we cast or convert between types using the less than and greater than signs, so it actually kind of looks like an HTML tag in a way, but it's a casting syntax. And then finally, we can actually define types, such as string, number, and Boolean in TypeScript, and you'll see that we're going to separate the names of our variables, functions, and things like that with a colon. And that's going to be our separator between that name of the variable and the type, such as number, if we were defining maybe age or something like that. So as mentioned, we're going to be going through all these different keywords and the operators and even some more things that aren't here later throughout this course. To wrap up this section, let's talk about the code hierarchy that you're going to encounter as you work with TypeScript code. In JavaScript, we really just have functions, but using some of the different patterns out there, like the revealing module pattern, we can simulate a hierarchy and we can even include things like name spaces in JavaScript to take things out of the global scope. Well in TypeScript, there's a very defined hierarchy that's just built in, and we'll be covering all aspects of this throughout the course. So at the top level, we have modules. And modules act as a naming container that can export different members. Now inside of modules, you can actually have different things and different types of code, but one of the key things that you'll have is a class. A class, of course, is just a container for different members and specifically TypeScript classes can have fields, a constructor for initialization, properties, and functions. Now classes can also implement interfaces in cases where we want to drive consistency across multiple classes. Now there's certainly more to the picture than shown here, and we'll be covering more details, but this is the overall hierarchy that you'll be working with as you build your TypeScript applications.
Tooling and Framework Options
One of the areas where TypeScript really excels is in its support for tooling and frameworks that are out there. And that's actually a big deal, because as we're writing enterprise-scale JavaScript applications, we typically have quite a bit of code, and we don't want small issues turning into larger issues. We want to catch them up front. Well, by having robust support for tooling and frameworks, TypeScript makes it much easier to catch issues up front before they do become a big deal. So in this section, we're going to talk about some of the different tooling and framework options that are out there. Now one of the service-side frameworks that's very popular, that's fully supported by TypeScript is Node.js. Node.js allows you to write service-side applications in JavaScript, and then, of course, you can render HTML if you want. You could serve up JSON data or a variety of other things, but TypeScript can be used directly with Node.js. In fact, it even knows about Node.js and can generate the JavaScript. You can also use it with different editors, such as Sublime, Emacs, or Vi. And then Visual Studio has excellent support for TypeScript, including when you save, it'll actually auto compile, and you'll get a JavaScript file out of the box. And I'll demonstrate some of these different tools coming up. And then finally, if you want, you could just go to the typescriptlang.org site, and you can actually work with TypeScript and even get help as you type directly in what's called the TypeScript Playground. Now the TypeScript Playground itself is just a webpage, and as you type over here on the left, this will be your TypeScript, you can see. Over on the right, it'll automatically generate the JavaScript, and then you could run it if you'd like, as well. So this provides a great way to get started with TypeScript, and as we mentioned, as you type, it'll actually help you with things like data types of your variables, give you Intellisense, and has some other features there to notify you if you've done something incorrectly. So let's go ahead and take a look at some tools and demos of using these tools with TypeScript.
Tooling and Framework Options - TypeScript Playground
One of the best ways to get started learning TypeScript is to head over to typescriptlang.org. And that's because we can get to tutorials, we can go to the playground, which I'll be coming to in this demo, we can get some plugins for different editors and frameworks, and we can even join in in the discussions and information about the TypeScript language itself, and even get details about the specification of TypeScript. But for this demo, I'm going to spend some time with the playground, because it's a great way to learn TypeScript without having to invest any time even opening an editor. You can just do it right in your browser. Now you can see right off the bat, it takes us to this walkthrough on classes, but there's several different options in here. And right off the bat, the default one shows a little class called greeter with a simple function called greet. Now you'll notice that we have a new instance of the greeter being created, and that we're passing this world into the constructor here. Now we'll be covering more details about functions and constructors and classes and all that throughout this course, but for now, what I want to show is what the playground gives you. And really what I'll show here is what other tools will give you as well, depending on the tool. Let's say that this was actually a number for the message. What you'll notice right off the bat we get errors, and as I mouse over these, it's telling me that, "Hey, you supplied a string, "but obviously it didn't like that. "Can't convert a number to a string." At least TypeScript won't implicitly. Now we can come in and maybe do two string, or something like that, but this is great because right off the bat, I'm able to see issues with my types. And that makes it a lot easier to catch issues up front. Now let's go ahead and we'll change that back into a string. Now let's say we wanted a new method in here or function. Let's say we had a show greeting. Now as I type the squiggly brackets, it's kind of nice. It'll automatically close 'em for me. And then I'm just going to say return, we'll say greeting. And then I'm going to purposely do a little typo here, and we're just going to say this dot greeting. Notice I'll get Intellisense, so it actually pops up what I'm allowed to select. But what I'm going to do here is leave it kind of messed up, and you'll notice it's catching that hey, we have a problem. And over here to the right, this is what was generated, ultimately once this TypeScript gets compiled down to JavaScript, and you'll see that it doesn't really work quite like we wanted. Now of course, the reason for that is we have a typo. I need to put a plus. Well, that's the type of things that it'll catch, just right here in the browser, and depending on your tool, it'll do the same type of thing, of course. So makes it great not only from the code standpoint of providing that kind of ravioli code we talked about. But it also, from a developer and editor's kind of relationship here, the editor really can help you out and identify some errors you might have up front, which I think is a great thing. The other thing I like is it's really easy to see the JavaScript that's being output. For instance, from our simple function here. And you can see that it's actually using the standard JavaScript prototype to extend the greeter object. So that's an example of what the TypeScript Playground is, and how you can get started learning TypeScript, and actually writing it and generating JavaScript without having to even open an editor.
Tooling and Framework Options - Visual Studio
We can go ahead and open up Visual Studio. And once this opens up, we can now create dot TS files. And a dot TS file is, of course, a TypeScript file, so let's go ahead and we'll do file new project, and in this case, I can actually come in and just select really any project I want. I'm just going to do an empty one. So we'll do an empty web application here. We'll call it TypeScript demo. And we'll save this to a folder I have called after. Alright, once it creates it, we'll have our empty project with a web dot config file, but we can now come in and add our TS files. Now the TS file is going to be the TypeScript file, but what's really nice about Visual Studio is that it'll automatically compile the TypeScript down to JavaScript. So we can come in, and let's go ahead and add, I usually have a JS or script folder, so we'll do new folder. We'll call this scripts. And then from here, I'm just going to right click and add a new item. And we'll come up to the installed templates. I'm just going to type type here, and you'll notice that TypeScript file comes up. Now we'll go ahead and just call this, we'll say main. And we'll add it in. Now this will add in a demonstration of the TypeScript language for us. So you'll notice that we have a module here called shapes. Nothing real fancy, but what's nice about this is if we come over to the solution explorer, underneath this, it automatically added a JavaScript file. So this is the JavaScript file that you would reference and include in your page. Now what's nice is you really don't have to do anything. As soon as I change something here, for instance, if we come in to getDist here, and we'll just call it get D. Alright, you'll notice right off the bat that I now have some problems down here because my get D down here, so the editor is telling us right off the bat that we have some problems. And there's a lot of other things I can change and fix here, but what's nice is the JavaScript language service here, as we saving things, if there's a problem it knows about, it'll actually tell us down here and tell us kind of how to fix it. So I'll go ahead and undo it. We'll be back to good. And now I can add a HTML file or ASP.net or whatever I'm doing, and simply reference this JS file, and I really never have to touch it. Every time I want to make an edit, I'll go into my TypeScript file to get started with it. Now from there, we can add multiple TypeScript files in, structure those in sub-folders, however you'd like to do it, but it makes it very, very easy to get started with. So that's how easy it is to get started using TypeScript with Visual Studio 2012.
Tooling and Framework Options - Web Essentials
Although you can use TypeScript directly in Visual Studio, if you want to actually see the JavaScript that's generated, you're going to have to drill down under TypeScript and get the JavaScript file. Now most of the time, you'd be writing TypeScript directly and probably not want to touch the JavaScript anyway, but if you'd like to see it at the same time, and actually see a live view of the JavaScript that's generated as you write your TypeScript, really good way to learn, by the way. Then there's a really nice add-in we can do for Visual Studio called Web Essentials. So what I'm going to show is how to get that going here. So if we go up to tools, extensions, and updates, then we can go to online, and Web Essentials is actually a very, very popular tool. If you don't already have it, it does all kinds of great stuff with CSS to make it easier to work with colors, work with vendor prefixes, and do a lot of web-related activities. It's actually a very good tool and I highly recommend it. It also now supports the ability to work with TypeScript. So if we didn't find it here in the top or most popular ones, we could certainly just search for it, but we're going to go ahead and download it. And we'll install this, and restart Visual Studio and let's see what happens here. Now what you're going to see is that it's going to allow me to actually work with TypeScript and see the JavaScript simultaneously, which works out really well. So once this loaded, let's go ahead and open up. We'll open up our TypeScript file and there we go. So we'll go ahead and minimize our solution explorer. And notice that now, as I type, I actually get information and this is the JavaScript file that it's loading. Now again, this is something that, most of the time, if you're doing TypeScript, you'd probably just want to work with the TypeScript, but this is great in situations where you'd like to see both, if nothing else for learning, or just to make sure that you're putting is ultimately what you want output when it comes to the JavaScript. And it saves you having to open that JavaScript file. So that's a quick look at the Web Essentials tool.
Tooling and Framework Options - Sublime Text
TypeScript supports a variety of editors, so you're not just locked down to using a Microsoft editor, such as Visual Studio. You can use others like Sublime, Emacs, Vi, and others. Now in this demo, I'm going to show how we can integrate some TypeScript, syntax highlighting, and a custom build option into Sublime text. And to get started, you'll want to head over to typescriptlang.org, and then click on get it. Now don't click on download the plugin, because that'll get you the Visual Studio plugin, at least at this point. But if we click right up above here, you'll see other editors available. Now currently, this takes us off to the interoperability site for Microsoft and they're actually soliciting feedback on where to host some of these editor scripts and files. But for now, this is where we go and if we move on down to the bottom from here, you'll see we get TypeScript support for Sublime text. So this is a zip file I'm going to go ahead and download. And inside of the zip file, you'll see this TM lang file. Now this is your language syntax highlighting for TypeScript, and so I'm just going to copy that. And we need to copy this into, it's a little bit buried deep on the hard drive, but I already have it open. Full path is off of your C drive. Go to your user account, App Data, Roaming, and then you'll see Sublime text two, packages user. And I'm just going to paste that right inside there. And that'll give us syntax highlighting out of the box. So now I'm going to open up Sublime, and we'll do a new file here. And I can start off doing some TypeScript. So we can do a class, we'll just call it car. And you'll notice nothing real impressive so far. I'm not getting really any highlighting, and that's because this file doesn't have an extension yet. So let's go ahead and save it. And we'll just call it Car.ts for TypeScript. And there we go. And now as I type different things, we might have an engine type that is a number. You'll see that I get some nice highlighting here, if I do a constructor for TypeScript. And we pass in the engine to use, which is a number. And then in here, we could say engine type. Notice I'm getting Intellisense or code help as I type here, which is really nice. So we can say engine. And that's an example of how easy it is. Now from here though, I'd have to run off and use the TSC dot exe, which is the TypeScript compiler to actually do anything with this, because we'd have to compile this down, obviously, to JavaScript. This isn't really a completed class, but it's good enough to mess around with. Now if I just save this, and we run off to the desktop, there won't be anything fancy here, other than the TypeScript file, just as you'd expect. So a nice thing you can do is if we come up to tools, we can go to build system, new build system. Now inside of here, I'm just going to wipe out what it gives us. We can actually come in and this is a specific build system file that I found out there on the web that you can use to make it so that you can do control B for build, and your TypeScript file will automatically get compiled right there in Sublime, down to JavaScript. So it makes it really, really easy to work with it. So all you'd have to do is get this syntax that you see right here into the build file that I just created. And now we're going to go ahead and save that. Now I'm just going to call it TypeScript.sublime-build. And we're good to go. So what this will do now is because I have this build file, if I do a control B, because we have a dot TS extension, this is our source file, and it'll automatically get compiled now to JavaScript. So let's do a control B here. You'll notice down here below, says it's finished. We'll run off to the desktop and there we go. And you can see that I have my JavaScript file that was created based upon my TypeScript file, and I didn't even have to resort to the command line to compile it. And so by integrating this custom build option, makes it really, really easy to work with. That'll now be available. So you'll see TypeScript's now available here. So that's an example of how easy it is to get syntax highlighting and a custom build option into Sublime text for TypeScript.
Tooling and Framework Options - TypeScript Compiler
As you work with TypeScript, you're going to need to compile it down to JavaScript. Now some of the editors like Visual Studio or Sublime if you add a custom build system in and others will allow you with either a hot key or simply by saving to generate JavaScript from your TypeScript, but in this demo, I'm going to show you how to do it from scratch, and use the TypeScript compiler, which is TSC.exe. So if you go to the TypeScript Playground, they already have this built into their web application. So as I type over here, it automatically updates over here. But what I'm going to do is just grab this greeter class. Now let's open up Notepad. And I'll paste this in the Notepad now, and let's save this. And I'm going to save it to my desktop in a code folder. And we'll just call this Greeter.ts for TypeScript. And save that there. Alright, so now we've saved it, but obviously, that's the TypeScript code. Certainly a browser's not going to know what to do with this. So we need to run a command line utility, TSC.exe, to actually compile this. So it's pretty easy. So I'm going to go back and let's load up a command prompt. And we can just load up a standard, regular old command prompt here. And from here, I'm going to navigate to the desktop. Let's go CD desktop, and we'll go into that code folder. Right, now all I have to do is TSC.exe or I can leave that off, of course, and we can type the file, which is Greeter.ts, and we'll hit enter. And there we go. So let's run off to the after folder here. And you'll see that we now have our greeter file, and this would be our JavaScript version of that class that we created in TypeScript. Now that's as simple as it is. That's really all you have to do. Now of course, if you want to get some help, we can just type TSC and do nothing here, and this will show us some of the different arguments and options that we can pass in, such as comments and declarations, and there's quite a bit you can do, but at a minimum, all you have to do is TSC.exe and then give it your TypeScript file and you're off and running. So that's an example of using the TypeScript compiler.
Tooling and Framework Options - NodeJS
TypeScript can be used with several different frameworks, in addition to all the editors that we've talked about. And one of those is Node.js. And that's what I'm going to show here in this demonstration. So Node.js is a scalable, asynchronous, event-driven type of model for building applications. Typically, you'll see it used on the server-side to serve up web pages or JSON data or something along those lines, but it does actually quite a few different things. TypeScript can be used to build Node.js applications, and to get started, you can actually head over to typescriptlang.org. Click on get it. And you'll see a section here on Node.js. Fortunately, there's a package out there called TypeScript that we can install with a Node package manager or MPM, and actually run it directly, and then we'll get the compiler and all those goodies that we need to compile from TypeScript down to JavaScript. So I already have Node installed, and I'm going to go ahead and use the node package manager. And so we'll just run MPM, we'll do install, and we're going to install TypeScript. That'll run out and grab it, and install it here locally, and you'll see the location here of where it put everything. So now we have the compiler. Now from here, I could run the TSC.exe to actually compile from TypeScript down to JavaScript, but I'm going to go ahead and use Visual Studio here to show off a cool feature that we can use with Node. Let's go ahead and close this, and we'll go over to Visual Studio. Now I've created a real simple project here. This is kind of the hello world of Node, where we're going to spawn up a ACTP server. And the ACTP server's just going to return hello from Node.js, so very basic. So first off, you'll notice up top that we have a reference to this node.d.ts, and this is a definition file, which I have included. And this definition file actually defines all the interfaces, parameter types, and everything you need to know to get started with Node and some of the key modules that are out there. And so, for instance, the console.log. Very popular thing to do in Node. And you can get to that and actually see what you're allowed to pass, which in this case, is pretty much anything. And as we scroll down through here, you'll see there's our require, we have information about modules, and much, much more. It's a pretty large file you can see in here. Now what makes Visual Studio really great for this though, is as I'm writing code, I get excellent Intellisense, and it's going to tell me data types of different parameters to pass, and if I mess up, it'll tell me. So just as an example here, if we were to take off this line and just do ACTP dot, you'll see that I get access to create client or create server. And when I do that, in the parentheses here, it tells me that we need to set up a listener and the function, which is our callback function, is going to have a server request and a server response object. And those, of course, might have some properties in them. Now I'll go back to what I had here. We can come down here to write head, as an example. If we do response dot, if we do right head, you'll see that we actually get information here about what we're allowed to pass, and we can see the data types of some of these, as well. So it makes it really convenient to get started working with this, and you can actually write this TypeScript up. Because it's in Visual Studio, I don't even have to run TSC.exe. I showed how we could use MPM to get that package downloaded with a compiler. But if you're using Visual Studio, you could just save, if you have the Visual Studio plugin for TypeScript installed, which I do here. And as a result, we'll get our server JS here. And you'll notice it even has a server min JS, which compresses everything down or minimizes it. Right, so that's some of the benefits you'll get out of the box with Node and TypeScript and kind of tying an editor into the mix. Now again with Node, you could use anything. You could use Sublime, you could use Notepad, if you wanted. But I wanted to show off how Visual Studio actually adds some excellent Intellisense to help you out as you're working with Node. Now to go ahead and run this, we can just run off to a command prompt, so I'm going to shift, right click to get to our command prompt here. And we can do Node, and then we have to run our JS file, so it's called server.js. And it's now listening. Now we can pop up on the browser and basically the port that I have here, which is 1500, I should now be able to hit. So let's go to local host, 1500, and you can see hello from Node.js. So that's an example of how we can use a Node definition file for TypeScript to actually get enhanced IntelliSense in Visual Studio when we're building Node.js applications.
Hello World Example
We've hit that magic moment when we get to do a hello world example. So what I'm going to do in the demo that follows is walk you through some extreme fundamentals, just to break you in. We're going to go ahead and use Visual Studio for this particular demo, but we could use any of the other editors that we talked about, as well. And just walk through some of the core fundamentals that we'll be covering later throughout this course. So let's jump in.
Hello World Example - Creating a Class
Let's take a look at how we can get started using TypeScript, and I'm going to use Visual Studio 2012 for this demo, but we could certainly use any editor out there, including Notepad, if we wanted. But Visual Studio provides very robust support for TypeScript, so I'll do the demo in that. So to get started, I'm going to click on new project. Now we can literally just create a website project, a web form, an MVC, or there's even a TypeScript option. Really, it doesn't matter. You just have to name your TypeScript files dot TS as you'll see, so I'm just going to pick an empty ASP.NET web application. And it's going to be more of an HTML-type app, but we'll call this hello world TypeScript. And let me go ahead and save this to after. Okay. Now this will create an empty project. We'll get a web config, which I'm just going to delete because we don't really need it here. And now I'm going to add a folder for scripts, so we'll come down and do new folder. Alright, now from here, all I have to do is add a dot TS file. Now if I go in and do new item, I could come in and type TypeScript. And you'll see we get TypeScript file, but keep in mind, I could also just select a text file and just name it as a dot TS file, as well. So it doesn't really matter as long as it's a TS file, but we'll go ahead and select this one. And I'm just going to call this Car.ts. Alright, now you'll notice right off the bat that I'm able to see two things here. And that's because if we go up to tools, extensions and updates, I have not only the TypeScript for Visual Studio installed, but I also have the Web Essentials 2012, as I showed earlier in this module. And what that does is allows me to see both. Now in this case, I really don't need to see it, so I'm just going to slide this off. And you'll notice it compacts up really nicely, and we're ready to go. Now over here, you'll notice that we have a Car.js, and that, of course, is going to have the default code that we get out of the box, which I'm going to promptly delete all this. So I'm going to highlight all my TypeScript code, and we'll delete it. And we're going to create a class here called car. And car is going to have an engine, and the engine, we're going to set through the constructor, so I'm not going to do this.engine for the actual variable, but we will do that, you'll see, in the constructor. And so I'm just going to say engine, and I'm going to type that as a string. And then I'm going to add a constructor. Now in the constructor, I want to be able to pass in the engine type, and so we'll go ahead and we'll say that we can pass in the engine, which is, of course, going to be a string. And we'll simply assign that up to our engine, and we need to use the this keyword for this. And the reason for that is we want engine to be unique to this instance of the engine. And so whereas in C# and some other languages, this is not really required, per se. It is in this case with TypeScript. Now notice I get Intellisense, pretty nice. And we'll just say that equals engine. Alright, now all I'm going to do from here is we'll do a function called start. And you'll going to see I'm going to change this up, actually. It's not going to work, and a function called stop. And the reason I'm going to do this is I'm going to note, first off, that you'll notice I'm getting an error here. Doesn't like it. That's because in TypeScript, we actually don't put the keyword function, but if I were to move this outside of the class, you'll notice that it works fine. And this is one of my favorite features of TypeScript, in addition to the type support and editor support and classes, and all that good stuff. You can take standard JavaScript and actually plug it in, and it's just going to work because TypeScript is a superset of JavaScript. Alright, now how do we fix it? Well, let's come back up. And all we do is take off the function keyword. And you'll see this will work now. And all I'm going to do is something very basic again. Kind of a hello world example here. We're going to say engine started. And I'm just going to put the name of the, the type of the engine, which will be the one that was passed in. And then we'll do the same thing in the stop. And we'll say engine stopped. And we'll say the type of engine that was passed in. Alright, so this really defines the core members of a class in TypeScript, so we have variables, we have a constructor for when it's initialized, we have our start and our stop functions, and of course, there's more we could do with TypeScript, which we'll be covering later in the course, but this is a good beginning. Alright, so that is our car class. Really simple, doesn't do a whole lot, obviously, at this point, but this is kind of our basic hello world demo. Now what I'm going to do from here is we're going to come down, and I want to add the window unload capability. I'm not using jQuery or another library to handle like a ready, so I'm just going to do window unload. And you'll notice, again, I can just type standard JavaScript. And so I'm going to put that in. Well end it, and then I'm going to create a new car, so we'll say car equals new car. Now notice I'm going to get Intellisense that says I need to pass in an engine. We'll pass in a V8, and you could use double quotes or single quotes here, so in JavaScript, I generally prefer to do single quotes, and I'm still sort of doing that with my TypeScript, but it really doesn't matter. So we'll do a V8 engine. And then we'll call car.start. And car.stop. Alright, so because I have Web Essentials installed, I can just slide over if I want to easily see what's going to happen. You'll notice that we have our car. We have our window unload when it's called, we'll invoke a new car, and we'll call in start and we'll call stop as far as the functions. So as shown earlier, you'll see that we're doing car.prototype, or TypeScript is generated in this type of code for us, and then we do the alert. So the next thing I'm going to do is let's slide this back over, is look over here to the right, and also because I have Web Essentials installed, you'll notice I get a minimized version of that. And that's something I could reference, of course, in my file, my HTML file. So let's go ahead and add that. And we'll add a new item, and we'll select an HTML file here. Alright, so all I'm going to do is we're going to drag in, I'll just drag in the min just to show it works, a script here, and we're pretty much ready to go. So let's go ahead and right click and view in browser. And we should see that we get a start and a stop recalled, and there we go. Engine started V8, engine stopped V8. So that's a simple example, more of a hello world-type example of getting started with TypeScript. So as a quick review, you can use any type of project you'd like. A standard web project for web forms, you could do MVC, it really doesn't matter, actually, as long as you name your extension dot TS here. That's the magic that makes it so it'll automatically save it and generate the JavaScript. At least in Visual Studio. In addition to that, we've seen that we can do our modularity here with classes. We can type our variables, not only as our variable here, but also as parameters, and that we can actually use standard JavaScript inside of a TypeScript file, which makes it really, really easy to get started with TypeScript. And then we've seen how tools like Web Essentials can actually give us the ability to see the JavaScript and even generate a kind of minified version, if you will, of that JavaScript. So that's a quick example of getting started with TypeScript.
Summary
In this module, we started off by talking about some of the different challenges that face us as JavaScript developers with probably the biggest challenge being how do we structure our code, especially in large-scale applications? We don't want to write spaghetti code. We want more of ravioli code or encapsulated modular code. We talked about some of the different ways that TypeScript can help with that, and what it is. And that because it's just a superset of JavaScript that you can use regular JavaScript with it, but that it adds additional features like classes and modules to provide that modularity in our code base. We also talked about the type support that's built in, and how that helps us ensure that proper types are being passed around between methods and, as they're assigned, variables. Finally, we talked about different tools and frameworks that you can use TypeScript with. On the server side, you can use something like Node.js, which is a very popular JavaScript server-side framework, and TypeScript can actually generate the code for Node.js applications. And then, of course, when it comes to editors, there's quite a wide variety that support it. Everything from Vi to Emacs to Visual Studio to Sublime, and I'm sure there will be even more as TypeScript continues to grow and grow. So now that we've covered some of the fundamentals of what TypeScript is, some of the challenges it helps solve, and some of the tools it offers that we can use with it, let's jump into some additional details now about what TypeScript offers us as a language.
Typing, Variables, and Functions
Overview
In this module, I'm going to cover all the core features of TypeScript so you can get coding right away. It'll be a jumpstart into things like the grammar and the syntax and how to deal with declarations and annotated types, so we can deal with and understand what static typing is in TypeScript and why and when you need it. We'll cover things like the different primitive types that are available in TypeScript, go over some of the new types like any, and handle -- how we do with things like functions and object literals and arrays, things that JavaScript already has and how do they translate over the TypeScript so we can use those in defining all of our objects and functions as we go along. So by the end of this module, you'll understand all the core features you need to know to get coding with TypeScript right away, and some tips and tricks with the tooling. ( Silence )
Grammar, Declarations, and Annotations
It's important to first start with what the basic syntax and grammar of TypeScript is, so in this section we'll go over the grammar and declarations and different kind of type annotations you can use with TypeScript. In this first example, we're going to take a look at type inference. We'll break down the syntax that we have for TypeScript. Now we could see we're creating a variable called "num" and setting it to a value of two or initializing it to two. So how do we break this out? First we declare using var, same thing we do in JavaScript we do in TypeScript. And then we're going to say, "Name this N-U-M -- num." Now by naming this, we're giving it a unique identifier that we can refer to this variable as. And finally, we can set the value equal to two, or initializing it here. This is the same thing we do in TypeScript and in JavaScript, and in fact this JavaScript code will work in TypeScript exactly as is. But there's an important subtlety to this code, as well. Notice that this num is equal to two. It's actually using type inference to determine that num is going to be of typed number. Why? Because the initialized value is equal to two which is a number, so therefore in the code, anytime you use num it's going to automatically assume that num is going to be a number and it'll type check for you in the TypeScript side. So we didn't have to declare it as a type number, we can just use type inference to assume this is a number in this case. In this example, we have the same kind of variable, num, and we're setting it to two, but now we're going to use a type annotation to clearly define explicitly that it's of number. So we're going to declare it again with var, we're going to create a variable called num, and now we have this new thing, this colon in here, we're using annotation, let's say. Following this annotation we're going to set the type of num, and the type of num is going to be number, which is a type that's built in to TypeScript and that number is going to be equal to two. We're getting the same thing with what you had in the previous example where we have a variable called num which is going to be of type number equal to two. Just in this case, we're clearly defining that it's a type number. We don't have to actually set the value here either. That's the cool part about the type annotations. We could just say "var num colon number" and then put the semicolon there, and then we have a variable called num which is of type number all throughout our code. But we can optionally set the value in this line, as well. So by using the annotations, you'll get a little more power and flexibility. Let's look at some more examples. Here we can see that we've got a variable called "any1." We're not setting it to anything and we're not defining it as a specific type using annotation. So in this case, the inference is that this could be any type at all. And in fact in TypeScript, there's a type called "any" and it's the base type for all types. So we can set this to a string later or a number or anything we want, or an object. In this example, we've got a variable called num1 and we're setting it to be a type of number. So we're using annotation here, we're not initializing it to anything but we're just saying that num1 anywhere we use it has to be a number. And then we have the same exact were we had before, where we're saying num2 is equal to number, same as num1 is, but in this case we're going to initialize it to a value of two which will work for us. Next, we have num3 equals 3. Now in this case we didn't define it as of any particular type, but because of type inference, again, this is going to be a number. So in all cases of num1, num2 and num3, they're actually all going to be of type number. Now in this case you've got num4, again, we're using type inference and because num3 and 100 are both numbers it's going to infer that num4 must also be a number. So it's just different ways that you can use type inference and the annotations to show that the values are there. The recommended approach I use when creating TypeScript is to use what we do with num2 there. That's a var num2, colon, what's the type; and then if I want to initialize it, I would initialize it to something. Just some other examples here, we've got a string now we're we've got "str1 equals num1 plus "some string."" Now this will work, you might first think it wouldn't, but what's going to happen is going to take num1, which is a number, and it's going to concatenate it together with a string value, a string literal. And because you can do that, it's going to actually convert that over to be a string, so str1 will be of type string. Now what's an example that wouldn't work? So now we have a variable called "nothappy" and nothappy is being clearly defined as a number, and then I say take num1, add it to some string, so I'm adding a number to a string, in this case we're trying to return it to a number and that's just not going to work. So the good news is in all the editors like Visual Studio, it's going to actually underline this and tell you, "Look, you can't do that. You're trying to set a value that's going to be a string to a number," and that just doesn't work in this case. So now we've covered some of the basic examples, let's go on to dive in some more in the code. ( Silence )
Type Inference
Let's start creating some TypeScript now, and we'll open up the TypeScript types project file that is inside of the module two before folder. And first, let's go to the scripts folder and we'll add a new file. We could choose Add New Item and in the installed templates we can type in "type." Now we can see the TypeScript file here and we can call this file "grammar" (typing) because that's what we're checking out the grammar and the syntax. So once we get that, you'll notice there's some predefined code in here. I'm going to highlight it all with ctrl A and delete it, so we're not going to start out with any other TypeScript, we're going to type our own in here. And a little hint we have is we use the Web Essentials tool that Dan mentioned in module one, we can set up a preview window to see what the code will look like. Well let's do that, we're going to Tools, Options. If you've installed Web Essentials, you'll see it down here and you've got the options under there for TypeScript. A couple of these things that are really important. First, if you're using EcmaScript Three, you want to turn that on to "true." If you want to support EcmaScript Five, then you'll leave that to "false." And then, we can generate a source map, we'll take a look at that when we get to doing debugging. We'll leave that off for now. If I want to keep the comments in there, so I type "comments," it'll automatically put the comments in the JavaScript file, I'll leave that to "true." And then we can also handle things like generating files in the projects, we're going to add them into the project file, we'll get that on for "true" for now. You want to compile all the files on build, I want that to be "false." I only want the compile one saved, so whenever I press "Save" or ctrl S, it's automatically going to take the TypeScript and convert it to JavaScript. And then if I want to, I can create a minify file, too. And one option I do want to change is to set the show preview window to "true." So when I do this, now whenever I type in TypeScript I'm going to automatically have a preview window. So I come back in TypeScript file, now you can see that I've got a preview window over here. It's a little out of sync. Simply, I can just type in something like "var x equals 1," and when I press Save, now you can see on the right-hand side I've got my JavaScript; so the left-hand side is TypeScript, the right-hand side is JavaScript. So we've created this var x up here and when I hover over x, you can see it's automatically inferring that x is a number. It's because we automatically initialized it to one, which is a number. Now if I come down and type in another variable like y, you'll notice that y when I hover over it is any. Any is the base type of all other types in TypeScript, so it can't determine if it's a number, or a string, or a day or anything else, so it's just inferring that it's going to be the base type. So you could type in other types as well. We can say in here that we something like first name. Notice that first name is of type string because it sees that it's set to a string literal. We can also go and type in something like last name. Now, notice when I type in last name it's also a string. The output over here for the JavaScript is exactly the same for first name and for last name. Notice that the type string here that I've used with the annotations is only in the TypeScript. That's not a valid JavaScript so it doesn't output it or emit it over the right-hand side in the preview window. So you're seeing as you type what that JavaScript is, and it's a very handy tool as you're learning to see, "Okay. What do I type in TypeScript? What am I getting in JavaScript?" Well, now let's type some other values here. Well, I'll go ahead and create a number called number1 and we're going to define that as just number 10 or a 100. And we'll create a number2 and this one we'll just say it's actually a number, and we'll define that one to be 20. Again, we've got both of them being numbers here and one is explicit because we're using an annotation; the other one is not explicit because it's being inferred by the right-hand side. I don't recommend you mix and match (chuckle) but just showing here for demonstrations, we could have done this. Now let's see we create a function. We want to add these numbers together. So what we do is we'd accept in three numbers and we want return the results of what these three numbers are. So simply we can define a variable that's going to accept the result and once we get that result, then we can just message it out to the user. So now that we have our function here, we can see over in the JavaScript it was generated the same way. We didn't write any TypeScript code on the left-hand side, it's all just basic JavaScript so it's exactly what it emits on the right-hand side. Now it's accepting in three different variables, all these variables are just going to type any. Notice we've got n1 here, we've got n2 and n3. And result because it's adding in three any's, it's going to be nany. It's going to take message and turn it into a string because it sees a literal being put together with an any and then it's going to alert out a string. So we're good to go on these but let's actually call this. So now we could say add these numbers and we can pass in num1 as we've defined it up top as 100 and that's a number. We could pass in num2, that's also a number and let's pass in the last name. (Typing) Now you might think now this isn't going to work, but it is going to work in this case because what's going to happen is we're passing in the number, and another number, and then it's going to take the names. So the results in this case are going to add those two numbers and put them in with the string and it's going to treat them all the strings. So when we pass in number1, which can be 100; number 2 is 20; and then the last name of "Papa" is actually going to add the first two numbers together and then concatenate the last name with it. Really, it's going to be unpredictable, so it's really going to happen. So if I run this now, (computer sound) we can see the sum as a "120Papa"; it's not really what I wanted, I wanted to add three numbers together, maybe add some type checking in there. So instead what I could've done is use some TypeScript to say, "You know, this number here, it's got to be a number. That's my parameter." And we'll move over the preview window, and then I also want this number to be a parameter and then there would be a parameter, as well. So now, notice what happens. I've now defined addNumbers to accept three numbers and it has to have three numbers. Whereas I'm calling over here and addNumbers is right in the editor, it's telling me that it doesn't match the signature of the call target. I've got a number, a number, and a string, so I can quickly just change this out, I got to put another number in there like seven -- if I wanted to, everything's happy; and now when I run this in the browser we should get the real results, (computer sound) sum is 127. So this is one way you can use typing using inference. Basically here we've got the inferring the type or we can use annotations to define the type. ( Silence )
Grammar
Now that we've learned about the basics of static typing with TypeScript, let's take at another example. This one is in "02-02-timer.ts" and this is in your starter solution in module two. Now when we open this up, we can see some code in here for creating a timer. It's going to basically create a timer on the screen where you can count for minutes, seconds, and milliseconds using an interval 25 milliseconds. But right out of the bat, we've got a couple of errors in our page. First is showing us because we're using TypeScript that we've got the second it does not exist in the current scope, so we can double-click on that. And we could see down here the innerHTML, we've got a variable called "second" which has been mistyped and is not accurate; and actually it's supposed to be "seconds" plural as we can see up to the top up here. So we can easily fix that, now that we have the underline in there. This saves us a lot of time, so the advantage of having statically typed language so we can make these fixes now, before we actually run the code. Now we could see two other errors. Now we've got a supplied parameter doesn't match any signature of the call. We click on that, we can see display timer is down here and we're passing a value of "true" into it. Well if I go and look for display timer, we can now see that the function is up here, it actually doesn't accept any parameters. Now in JavaScript, we could pass in a parameter and it would just ignore it. So in JavaScript that actually wouldn't cause an error, but it's showing us here that we actually probably more like a logic error going on. We're expecting something to happen with this true value when we write this, however, the function does nothing with it, so it's better off just to get rid of that. Or, if we actually wanted to do something based upon true like -- show it -- like only showing the display timer when the value comes in as, true as opposed to false, we can put some logic inside of our function. So it's helping us find problems with our code. Now a third issue we can see down here is another call parameter match. We got this init function which is passing in two strings. These are the names of elements on the screen for buttons that we can press, and then here we can see the init function has three parameters we can pass in actually. So one thing we can do is we can come down here and just put the third parameter into here and we could say this is the "clearButton." Here we have the three parameters that we can pass and we no longer have an error. Now we can run this page pretty simply and what I've done for the convenience is set up an index HTML on the root of your project, so we can run "Grammar -- Timer" and we hit that; and we press the "Play" button, we can see the milliseconds flying by; press "Pause," it'll stop it; we can also reset it; and if we hit the F12 key, we'll see the divider hop up. We can see there's no issues in the console, I'll refresh the page with ctrl R, and then we'll reset the timer and we can see that there's no issues in the console, no errors are popping up at all. So we can see it's pretty easy to do some debugging using TypeScript before we actually press run anywhere. There's some other things we could do as well though. You may notice that I'm not using explicit typing up here. I didn't have to because I'm putting the number values on the right-hand side. I'm initializing these variables but they're all actually number. But if I wanted to, and just to be explicit, I could stick in it's a number for all of these; and that wouldn't be too hard to do, and in fact, it wouldn't change any of the logic. And then on the right-hand side on the preview window, we can see the JavaScript that gets generated. It's still just putting out the JavaScript of each of the values and notice the typing doesn't actually show up on the right-hand side -- not a problem at all. One other thing we could do just to protect ourselves, and this is a nice place where TypeScript can really help you out, is let's say for the init I pass in three parameters, but nothing is stopping me from passing in a value down here, something like 111. So there's going to be no compile time error here because there's no problem which is passing in three parameters. All we care about is that this function signature has three parameters and there is the function itself. And notice the types are all any for each of these things. But when I try to wire up an event listener to the value of 111, it's going to break on me. When I go back to the index page and I run this, and I hit the timer again, notice I'm getting a script error for unable to add the event listener property. So let's get out of here and let's handle this a little bit better. One thing I could do is define the signature for this function to accept three string parameters. So let's define the init to actually have a type and this type is going to be a function that accepts three parameters. We'll use S for the Start button, probably a badly named parameter and that's going to be the string value that represents the element name; and p which is a string, and then c which is going to be a string. And those three other parameters are the startButton, pauseButton and clearButton, and that's going to be a function that returns actually nothing in this case, a "void." So what we're saying here is that the init function is of type, that's what the column means here, and we're going to pass in three parameters -- a string, a string, and another string for the Start, Pause, and Clear buttons, and then it's going to return, that's what the equals greater than sign means, a void, and that's because we're not actually returning anything. So now we define the type for a function in here. Before we're defining types of just regular variables like numbers and strings, now we're defining the types of the function itself. So now, if we don't pass in of an actual string down here, we're going to see the error right inside my IDE. Notice here we say the supply parameters do not match the signature, that's because when I click and hover over the init function, I'm seeing it's a string, a string, and a string. And down here, I've got a string, a string, and in this case this is a number. This is one of the advantages of using TypeScript because now we can just type in the simple clearButton, everything is good to go; we generate our JavaScript on the right-hand side, and notice everything's working perfectly. I can start and pause or stop. So what do we see here? We saw here how the grammar of TypeScript helps us check and find issues. Before we actually press run by using things like function definitions here, we've declared what the function is of type, in this case, three parameters of type string returning a void, actually not having returned value. And notice over here in the code, when we come down to the init function, it's just an init function and there's no typing over here, it's just the startButton, and pauseButton, and clearButton. So it doesn't change any of our JavaScript whatsoever, but it does make it a lot easier to write our code and have less bugs. ( Silence )
Static and Dynamic Typing
Typescript can really help us by creating static types in a dynamic world JavaScript. Now, there's nothing wrong with dynamic coding in JavaScript; actually I quite like it. In some cases it can really help you out. But and sometimes, it can be quite difficult to figure out what some of your bugs are, so this is where TypeScript can really help us. For example, in TypeScript, if you get static typing, you can actually make it optional. So if you like your JavaScript the way it is with dynamic typing, you can literally just copy your JavaScript over to TypeScript and therefore just use it in TypeScript as is, and it still will work. But you can optionally put static types on your variables. Typescript also gives us a feature that you don't get in the dynamic world, and that's type safety at compiled time. For example, if you have a variable that's going to represent different types in JavaScript, maybe a string in one case and an integer in another, maybe that was unintentional, those kind of things will be caught at runtime while you're debugging; probably it could be a really (chuckle) bad problem if it actually get passed that and gets to your users. But with type safety at compiled time right inside the IDE in Visual Studio, you can see that with TypeScript you've got this thing is defined as a string and later on using it as a number and therefore it'll tell you right away before you actually press Run. Well, let's look at an example here. So in JavaScript, we might have something like a person, and we create this person here and then we set equal to "John Papa." Now that could be any type. It happens to become a string when I set it to "John Papa," but it could be anything. So then later in my code I could say person.substring, one through four, no problem, and I get out the values that I want. But then let's say later on, somewhere down the line in my code I set person equals to one. Now very likely this was a mistake. I didn't mean to set it to a number, and well, realistically I was setting it to the return value of function. And if that function came back as being an integer in this case, then I might have an issue. Well, when I run this code at runtime, person.substringone four later, at runtime it's going to give me this object one as no method substring, that's because the number doesn't have that method; it's a number, not a string. So these are the kinds of things that can get caught with TypeScript by typing the variables inside your code. If I define person clearly as a string here before I ever press Run, the environment for development is going to tell me right away that this is a problem. But sometimes we have to write code that refers to other libraries, actually quite often we do that. And we do that, we want to be able to pull in the types from the other libraries too, but we don't control those types. So how do we do that with TypeScript? So let's look at an example here. In TypeScript, let's say that we had something like a document; we want to say "document.title." Now, this is on the DOM. What I could do is I could say "declare var document," and "declare" is a special word in TypeScript that creates an ambient declaration. So I'm saying here this variable, "var document," is going to be something that is referred to and I don't necessarily have it in my file. In this case, it's going to be the lib.d.ts file which is referenced by default by TypeScript. And this contains things about the DOM and JavaScript itself, like document. So now I can say document.title and it's going to automatically know this is a string, so I get all that out of the box which is great. And by introducing that variable, it's not going to have any impact on the JavaScript. It's still going to emit the same JavaScript we normally would expect. But what this gives us is it gives us the ability to get more development environment experience to say, "Hey, let's prevent any bugs that if I set title to the wrong thing, or I call the function with the wrong parameters, I'll find out right in the design environment." This also works for external libraries like jquery or Knockout, or underscore. So let's say we had something like a jquery call where we're setting this div text equals to some data value. Well, on TypeScript we can additionally add two things here. We're declaring var dollar sign. Now, here again we're doing ambient declaration, which is saying declare this dollar sign here, and then we're referencing this path to a definition file or a typings file for jquery, and you can grab this file off the CodePlex site for TypeScript. It's basically going to show you all the typings for jquery. It's something that they set out for us. So we can pull it down and say, "All right, we're going to reference this." We're also going to declare that any time we see dollar sign, we know that's not in this file, it's coming from somewhere else. I'm actually referencing it at my project from somewhere else, and it's going to provide all the types for jquery for me. So now I'm going to see all the IntelliSense for jquery and the types that are going to be there, all those annotations. And again on the JavaScript side, we're going to get the same old JavaScript we know and love, because these ambient declarations don't show up anywhere in the JavaScript. So between using the typings and the ambient declarations and the static optional types, we get a lot of bang for our buck without even pressing run. Now, let's take a look at a demonstration in code.
Compile Time or Run Time
Let's take a look at how we can create some dynamic types and see how the editor can help us find some bugs. So first, let's create a new file in the scripts folder, and the first thing we're going to do is delete out all the TypeScript that was created in there, and then we're going to go ahead and create a module name here. The module is basically just going to define a place where we can put all our variables. We'll learn more about modules in a later module. Pun is totally intended there. And let's create a variable called "person" and we'll call him "Papa." Now we've got this new variable here, and notice that when I highlight over "person," it's equal to a string by default because it's using type inference. But let's say we split this into two lines. So let's just do person here and now let's do it like this. So now, what do I have? I still got the same variable and it's going to equal to "John Papa" and the JavaScript will work fine, but it's now typed "any" because it can't figure out on the var line what happened there. It doesn't know if it's a number, or a string, an object or what. Now let's say that we did a console write line, where we did a console log and we're going to just put out the name, "person" -- not a problem whatsoever and that should work just fine. But now let's say later on in our code, somewhere in the future we create an object literal and we happen to name that thing "person." And in this case we're going to say the first name here is "Colleen," and let's say we've got an age on here and that's going to be 25, so we've got this person object now. Now let's say we did a console log down here. Well, that's going to be a little bit different, right? So we're going to be printing out the actual name up top, down below we're going to actually printing the object out. Let's go a little further on this though. Nothing is wrong with this code so far, but now let's do a substring with the first through four characters in there. So up top here, we're expecting, we're showing that we're expecting person to be a string. Now, this'll work just fine because it is a string. Down below, we're expecting person to be a string again. Now person in this case is not a string, so it's pretty obvious by looking at this that there's something wrong, but if you run this JavaScript, it'll indeed run just fine. We happen to have an index page here where we can browse to the examples. Let's click on the dynamic types, and you'll notice I'm getting an error here, "Object does not support the method "substring."" And we can just go ahead and look at the console window, and we can see the same error here; it's on line 10, character 5. So it's showing us here it's got a whole lot of problems with this console log person substring. So how do we fix that? Well, first of all we cannot name it's the same thing over and over again. So we could just have them here and create a new variable, call like "person2" and person2 would actually just be an object. And in fact what we wanted to do here was just do person2s name and then do a substring. Now I configure out here this name is a sting and that's a number because we typed them and initialize them. And again, if we initialize up here it would be fine, too. But, what can we do to solve this problem, so if we didn't know that that was so obvious of an error, if we had this code here, how do we fix that with annotations? By simply putting in a little bit of code like colon string. Now we've defined up top even if that wasn't initialized that that has to be a string. So right at compiled time, we're seeing there's a problem here. It says that we're trying to convert an object to a string and that isn't going to work. So we don't have to worry about running the code to find our errors because a lot of times you may not run across the code because there might be an event handler or something else, and that's where you're going to need a testing; and really if you want to find these kind of issues, it's a lot better if you're a development editor, it will show you these things right out of the gate. This is just one way that TypeScript's optional static typing can help you find problems without even pressing Run, right here in the editor.
Ambient Declarations and Type Definition Files
A lot of times in development we're going to be using external libraries. Let's show how TypeScript can help you when using external libraries, using the static typing with ambient declarations. First to start off, let's go in our project and create a new TypeScript file and we'll call this file "ambient declarations." And, again, we'll delete all the code that's in that window. And then we're going to install a package called "KnockoutJS" using NuGet. If you haven't used NuGet before, you can go get it by going to Tools, Extensions and Updates, you can install that as a NuGet package manager. You can see we have that here, and then go under View and then Other Windows and you'll find the package manager console, and once you open up that console you can type things in such as install package, and if you hit the tab you'll get IntelliSense. We're doing install package and I want to find one called "KnockoutJS." It's going to find that package and then it's going to install it into our project. Now Knockout, if you're not familiar with it, is a data-binding library for JavaScript and once it finds that, it's going to put it in my Scripts folders. And now if everything was successful, we should see Knockout debug and "knockout-2.2.0.js" in our project. Now, let's write some code using Knockout and see how TypeScript and its static typing and ambient declarations can help us. So first we're going to create a module inside of here and then we're going to create some variables. Let's go ahead and create a variable called "name," and that name we could normally set it to something like "John" as we did in the previous demo. But in Knockout, one of the things it does, it creates these observable properties. So we can do something like Knockout, "ko.observable," and we're going to create this property which is going to be of type ko.observable. So notice right out of the gate that we're getting a problem with TypeScript; it's telling us that it doesn't know what this "ko" thing is. It doesn't exist in the current scope; that's because we haven't told it yet that we have this library over here called Knockout. So let's tell it what "ko" is. First, we're going to say "declare var ko," and what we're saying is declare that we're going to have a variable called ko, and right now it's a type any because it doesn't know what it is, and it's making the error go away. So we set up an ambient declaration defining this ko variable, but it's still of type any. We want to help TypeScript understand what Knockout is so we can pull down these type definition files or typing files that we can use with TypeScript, so it has more information about it. And one thing you can do is go to the typescript.codeplex.com site and pull down under the typings folder the jquery.d.ts file. This is going to have all the typings for jquery so you can get basically IntelliSense and static typing for jquery. Another place you can go is the DefinitelyTyped GitHub project, then you can find a bunch of third party libraries that's being pulled into here and this is getting bigger and bigger all the time; and one of the libraries happens to be Knockout. So we can see Knockout right here and you can download this whole project and I've done that in advance to make it look easier for you. So if you look over in your module two code folder, you'll see a knockout-d.ts file, and over here you can see inside of there there's basically a bunch of typings for different properties that are in Knockout. We're going to do is pull that into the project. So first, we're going to create a new folder underneath the Scripts folder and we're going to call this "typings," just to have a place to store all these. And then, we're going to go ahead and add an existing item, and then we're going to go out to the code folder and find the knockout.ts file and we'll add it at the end of the project. Let me take a quick look at that here. We'll learn more about these d.ts files in one of the later modules, but for now I just know that it's helping define the different types for all the different properties in Knockout. So how do you reference that? How do you make this ko here know about that file? You simply just drag the typings file into your module and it sticks this reference up top for us. Now we move the declare out of the module over here, (typing) and remember, the declare is not going to show up anywhere in the JavaScript, so you can see on the right-hand side is not showing up at all. And now when I type in ko., you're going to see IntelliSense here. So if I type in observable, you'll see that and observable is then going to show you, "Look, there's five different overloads that you can have; you can have observable strings; you can have dates, numbers, Booleans, or any." So I can type in more code here like, let's set an identifier equal to ko.observable and we'll set that equal to one, and then let's go ahead and create an object and we'll call this object "guy." In guy, we're going to have a couple of properties, and the first one we're going to do is set up a property for identifier and we're going to set ID equal to ID, and then we're going to set another property and we'll just change the name just to have some fun here. So now I've created this guy object that's got an ID and a full name property. Now, we want to grab the value out of that guy object and get its full name, so let's create a variable called "value" and we'll define it as of type string, and we're going to say that the string value is going to be equal to "guy.fullName" and then we're going to have him and we're going to do about to the console and we're going to log the value for value. Oh, wait a minute, we have a problem. What's the issue here? guy.fullName, it says it's a string over here but it's actually not a string. That's because Knockout wrapped the string value inside of a function, this observable function. So to actually get to that, we'd have to put the open and close parenthesis at the end and that's going to return -- to be a function it returns a string; and whether you're a beginner or an expert at Knockout, you may make this mistake a lot. In fact, I do it quite often myself where I just say, "Hey, go get me that value right here or full name" and I forget that it's a function that returns the value. And now with TypeScript, I don't have to run my code to get that error. Normally, if I have JavaScript and I made that mistake, it wouldn't show me it in the development environment, it would only show it to me after I actually ran the code and sometimes even then it wouldn't, because this actually returns the function definition for full name for that observable. So it would take that, put it inside the value over here, which, if it was just a regular string, that would work just fine now because it's a value any; and then the JavaScript it would look just great and it would print out not the full name of "John Papa" but some function definition. So just by sticking in colon string right there, we could see that we had an error and we can correct it easily. So we've shown a couple of more advanced things in these section here, how in static typing can help you and really avoid making common debugging mistakes, and we did this by using ambient declarations to define this variable ko, we pulled in a type definition file, this typings for knockout, and then automatically we get all those great IntelliSense and compile time checking inside of our editor.
The Any Type and Primitives
Typescript allows us to use optional static typing with annotations, or inference, to go ahead and constrain values in our JavaScript. But there's also a type called any, and the any type is the one type that can represent any JavaScript value and there's no constraints with that whatsoever and that's basically just putting you back in dynamic mode of JavaScript. And any time we can't figure out what the type is going to be, it will be any. Let's take a look at some of these types here starting with any. So any can represent any value at all, so in both cases here whether you explicitly say data colon any, or you just leave off the typing, for info here they're both going to be able to represent any type at all, and that is basically the base type for all the types in TypeScript. There's no static type checking on anything with any. But there's also primitive types and all these are based off of any, so you've got numbers, or you've got Booleans, or you got strings, and in this case with the numbers, we can see here that the aid is set to a number explicitly and it's typed for that. And so is score, and then rating is using type inference to become a number. All three of those would actually represent as the number type. We've also got things like Booleans, with the "bool" keyword; and again, we can use explicit typing or we can use type inference with the "isReady" there to say that that's going to be a Boolean value. And finally, we have a string type where we can, again, use type inference or we can explicitly annotate the string to be -- for the first name to be "John." We can go one step further and look at arrays and indexers where we can define this names variable as being a string array. And then we're also initializing it to be a value with four strings in it. We could also use type inference there as well if we just left off the string array, and then when we define a value to be a string as in first person here using it to string annotation, then we can set the names indexer of zero equal to first person string, and that's going to work for us because the names indexer zero knows it contains a string value because of the string array annotation up above. There's other types, too, that are in primitives like null. The null type is something you can use on any of the primitive types, so you could have a number, or a string, or a bool, all set to null; and then you could also do that with an object type, too. And the null type is a subtype of all the primitives except for void and undefined. Void we'll look at when we get to doing arrow functions and undefined we'll look at next. The undefined type can be set for any of the primitives, too, so we could set a quantity to a number and that's going to be undefined right out of the gate because we haven't set anything. We haven't initialized it. So it's going to be of type number but it's also going to be undefined. And then the company here is going to be of type any and it will be undefined. Now that we've looked at the basics of the types, let's go over some examples to further explore them. ( Silence )
Applying Types
Let's create a new example here to go through some of the types. We'll create a new file inside of the Scripts folder and we'll call this "2-5-primitives," and again we'll go ahead and move the preview window to the side, we'll delete the TypeScript and we'll create a new module and then we'll go through the any types. We've looked at some of these already, so we could do something like create data and just define it as of type any, and then we could literally just put any value we want in there. Notice as I hover over, we're getting the tooltips of any type. We can also create a value in here for another variable like info and just leaving any off, we still have any. But you can use this for functions, too. So we could have a function called "doSomething" and then inside of that function let's say it just accepts some kind of an argument and we're not going to type the argument at all, and that doSomething might just, let's say, return the argument. (Chuckle) Actually, it doesn't do a whole lot. Maybe we should call it "doNothing." But notice here the doSomething becomes a type of function; it has an argument which accepts any value and returns an any value. So notice that arg is any, and also the return value is any. And then when I call that, you can pass in like five; it doesn't really matter what it gets. Notice its value of any is going into there an x will also become any. So it's inferring the type. In this case, x is inferring the type of doSomething, so the lack of having any is going to make them be an any. Lots of any's in there. So doSomething, I could make it any explicitly and I could define the argument as of any here, and then I could just say that's going to be any. It's kind of easy to do but let's just leave it off for now just to show how we did that. Let's move on to some of the primitive types. So let's create a primitive type for age and first we're going to set the number, say, it's going to be of type number and we could set that equal to like 21. We could also create something like a score and the score could be defined as a number and we don't have to use random just integers in here. So, now we can set up another type where we can use inference like a rating; maybe your rating is 99.9. In that case, we're going to infer those types, as well. All three of these will be of type number. What if we want to use a Boolean value? We could simply just come in here and create a value and set it be Boolean, and we can also initialize it to true. Notice now that "hasData" is set to Boolean of true. Well, we can also do the same thing without the Boolean of true here. Let's make it "hasData2"; it's also going to be a Boolean because it can infer because the type is true that it will be a Boolean for us. And let's create a function called "isBald" and it's going to check to see if somebody is bald, and you know what, it's going to return "yes" no matter (chuckle) what. So here we have an isBald function and what does that going to return? That's going to be a function that returns a type of string in this case. Now, you might think returning "yes" is going to be true. Let's say we have a hasHair variable, and that hasHair is going to be equal to isBald. Well, it should just end up returning a function for a string. Now, we've got the function name. Now, we're calling isBald as a function and return value becomes string, so it's inferring that it's a string in this case. But if I wanted "yes" or "no," or if I wanted a Boolean value, one way I could do that is I could negate that easily right here, so now I'm double-negating the return value of the function and it's going to check to see. This returning string of the yes that is a value; it's a truth value in JavaScript, and that it's going to negate that, and then negate it again, and it's going to infer that that's going to be a Boolean. Even with the simple negation there, it would still be a Boolean which is would be false in that case. So that's another way that you could actually create a value and use an inference. So now let's create some strings. So we saw some examples before where we had simple strings like first name, and then last name and they're both going to infer that it's a string. Well, we can also use string arrays. So let's say we create some kind of a function and we're going to pass in this value for this array as a variable called x and it's going to be of type string array. So what we could do before we write the return is to find a variable called length and that's going to equal x to zero, in this case we're just going to go out and get certain value. And we can actually use an indexer inside of there to get the value of whatever the first string is in there, or we can do "x.length" to get the length of the string, and then we can return length. So if we do that, let's examine what TypeScript did for us. It determines that "getArrayLength" is going to accept the parameter that's a string array and it's going to return a number. So it's inferring that this is a type number here because length is a number. So I could've gone through and to find that explicitly as a number here, create an array called "names" and let's make it to the string array and let's give it some values. So we'll set those up here. Once we have that string array, we can now say, "All right. Let me go ahead and get the first person out of there, and that first person is going to be a string and we'll set it to be names and we'll just get the zero with one -- which happens to be John, and go to the console (typing) and we'll log out the getArrayLength. And what we're doing now is expecting that with this array called "names" which has four elements in it, we're going to pass that in to getArrayLength and then we're going to get back the number 4. So when we do console log, we should see 4 in that case. And notice here, it sees it's accepting a string array and knows this is going to be a string array right here, so therefore our first person doesn't even need to have the string annotation there. If I take that away, notice that's going to infer the type up here, as well. Let's run the index HTML and then we've got the console window open and let's go ahead and click on the primitives, and you can see the number Four is being put out to the console window, very much what we've expected. So let's look at some of the null examples, too. So you have something like "guitarSales" and if I define that of type any, it can be a null. No problem at all. So notice here we've got our any type and it happens to be a null value, because null can be set to any of the primitive types in here, including the base type of any. So we can also say animal is a null, or we could just set up any kind of thing like an order date, and if order date was defined as the JavaScript date type, we can also set that to null, too. What about some undefineds? So let's create some undefined examples like quantity and set that to a number and we'll just initialize that to nothing. So it's going to be undefined and that's going to be set to undefined, as well. So undefined is a keyword. Notice the IntelliSense that I got when I typed undefined. We'll try that again. Undefined; it ends up being the keyword in TypeScript so that both of these, while one's a number and one's an any, they're both going to actually have a value of undefined. So if we wanted to see the values printed out to the console window, we could simply just print them out to the console and let's go ahead and rerun the index HTML. Now in the console window when I go to the primitives, you'll see there the undefined examples which is our beginner for that. We both have values of undefined for both the quantity and the company. So hopefully this shows you how you can have a lot of value by using the any base type and also the primitive types, both through explicit annotations with optional static typing and type inference.
Objects
In addition to the primitive types, we also have object types in TypeScript. Now, some of these examples are things like functions or class module, interface, or object literal types. All of these can be used in TypeScript to generate and emit standard JavaScript code. So we can have things like properties being either public or private on these objects. We can have required or optional parameters or properties. You can call signatures and methods, constructors or index signatures, as well. Let's take a look at some examples here. We can have an object literal where we've got two properties for it like height and width and we can set those. That's one way to create an object and it's going to use type inference to figure out that square is an object. We can also very explicitly define that points is going to be an object here is in the object keyword, in this case, points and square both can be objects. Functions are also objects, so this multiply function here is automatically use type inference to say that multiply is a function and it's going to return a number because it's going to use type inference to figure out that the return values number based upon the parameter is type dozen number. Now, let's say we had another function here called "multiplyMore." We could actually clearly define that as being a function using the function keyword with an uppercase F in TypeScript and then down later on in our code we could define multiplyMore as being set to be a function whose parameter is a number and returns back a number. These are just some of the ways we can define objects with TypeScript. Let's look at a few more. Let's create a new file in the Scripts folder. We'll call this "2-6-objects," we'll delete all the TypeScript that's in there and let's start off by creating an object called "points one"; and points one is going to be clearly defined as an object that has two properties, x and y. So if we go down and we use points one and we can look for properties, you're going to see them right there, so we could simply just go x equals -- well, not y. Now, if you want to continue on, we could create other objects, too. Let's create an object called "points two." (Typing) So if we do that, this guy here is going to be clearly defined as an object, but it doesn't have any properties in there, so if I go and use points two, I'm not going to see any properties coming up. We're just defining as an object, so we know it's going to be an object but we don't know what's going to be in it. However, we can still set it equal to anything we want. So if we want it to give it those values, we could do that here. This might be good if you wanted to have an object and you don't know what's going to come back from it later on. So another way we could do this is by doing points three and we're going to say now, we're going to define it as object using the object keyword. And this one here, we'd like to do something like this where you could just define the object, in this case it's just got one property called x. And, again, if I go into points three, it's not going to show me any of the object values are in there, but it does know it's a type object. So just a couple of different variations in how you can use an object. If you want an object that has specific properties and you expect them to be there, that's where you might want to use an interface and we'll learn more about those in the next module. Now, let's create a rectangle and we'll give this a height and a width and a calculation area function. Now that we have our object, we can use this rectangle and put out the value for the area by using the console log and we could just simply say, "Go ahead and get the rectangle.calcArea." If we'd like, we can put a little bit of message in front of it. So we run this in the browser, let's see what happens. We can go down to the view called "2-6-objects," which is already linked up to this code, and now we can see that a rectangle area is 200. What we've done is we've said that we've got this rectangle object and it's got three different properties. It's got a height and a width, which are both defined as numbers, and then it's got a calcArea which is defined as a function that returns a number, so it's a method. Basically the calcArea has no parameters and then it's returning back this equal sign and then the greater than sign, and that's basically a lambda, or known as an arrow function in TypeScript. So the arrow function is saying we're returning back a number, that's the return value. It's inferring that this is a number because these two are using an inference to figure out that they are numbers, indeed as well. Well, let's create another example for an object, something we saw in these slides earlier. We have a function called "squareIt," which accepts any number -- actually anything -- and then returns back a number. It's inferring that we're going to have a number return value because of the multiplication. And I can pass in this string and this is going to return back and not a number, not really what we wanted to do. So we can simply make this a little bit better by changing this to be, "Look, we want to pass in a number." And simply by doing that, notice the IntelliSense is telling me I have a problem with both of these functions. So now, what could I do with that? Well, I can simply just remove the parenthesis there and I don't want John there, let's just put in Eight, and then both of these will work just fine for us. Let's create a better version of this function. This time we're going to call it "squareIt" and it's going to be a function that's going to accept in a rectangle parameter, and that parameter is going to be of type object which is going to have a property called h will be a number, and a property called w which will be a number. And then, the function is going to perform some operation. Now, we're filling the details of the function in a moment, but pay careful attention to the question mark here. That question mark means there's an optional parameter, so we could pass in just the height, or the height and the width on this object. So what is squareIt expecting? SquareIt is expecting an object which will take the value from rectangle and it'll have a property in that object called h and a property called w optionally, and its return value in this case is going to be void right now. Void means nothing is going to be returned, so I definitely want to have a return value in here. First, what I could do is put in some logic to say, "Well, if I do have rectangle .w, which is the optional parameter, if that is there, I want to do one thing. If it's not, I want to do something else." So I'm going to check to see, if that's undefined, I want it to perform one action. In that case, I'm going to return back the height times the height; and if that's not the case, I'll return back the height times the width. Now, we can take a look at what happens. Now, they'll notice that the return value is a number because it's inferring that the number times the number is going to be the return value. And also, we've taken care of the case where if w doesn't exist, if it's undefined, we don't pass it in because it is optional, we're okay. Now, let's try it out. We'll create a variable called "sq1" and let's go ahead and call squareIt and we'll pass into that an object with a property value of 10 just for the height. And we can write him out to the console, and now we can see that 10 is going to be calculated. We're expecting to do another path where h times h will be returned. We can do the same kind of thing for sq2, so let's create a sq2 and this time let's pass in a value like 40 for the width, and then we print that out, we want to use this one here, where the height and width is of 10 and 40. So now what we're expecting to happen is we're expecting that we're going to get back 100 for here and 400 for there. A couple other things we could do. Now, notice that sq1 is going to be a number, so is sq2; it's using type inference again because the return value of squareIt is a number. But I could, if I wanted to, go ahead and explicitly type it as a number just in case that wasn't expected. For example, if I expected a string to come back out of this function, well, notice here I've got a problem. It's saying here that I've got a number and we're trying to set it to a string, so TypeScript is being smart for us and say "you can't do that." So we didn't have to explicitly type it here as a number. We could've just let type inference work, by leaving it blank, but let's try this out. Now, notice here we've got a height and width of 10 is not a number and the height and width of 40 is going to be 400. So we had a problem with this one here, well, it's probably because we didn't return anything back. So let's go back and look at our code, and here we can see we return back h times w and here -- oop, we forgot to put a return statement in. So now, we can return that out and therefore rectangle is going to work for us. Now, if we go back and browse to this again, now we can see that we've got the correct value coming out here as 100 and then it also adds 400. So we can see a couple of different things that we did with this. First, we can define that we had a function up top and that function has a parameter value which is going to be a parameter named "rect," and that parameter is going to be an object which has two properties, height and then width, width being optional. And, again, we could use interfaces to make this a little bit cleaner and we'll be taking a look at that pretty soon in module three. And then we move on to check to see, did we get a value in here for w? And if we did, we're okay. We're just going to go ahead and skip over that and return now to height times the width, otherwise, we'll just use the height times the height. We're going to assume it's a square if we only pass one value in. Let's take a look at the emitted JavaScript. If we go down to the bottom, we can see here we've got our function called squareIt, and notice it's accepting in rectangle and it's checking to see if it's undefined or not, and then emitting out the -- returning out the value that we wanted. Notice that there's no typings in here whatsoever; all those typings just happen in the TypeScript side. JavaScript, we're just getting plain old JavaScript which is exactly what we want, so the browser has no issues with any of this. Basically we're just putting all this syntactic sugar on top of the JavaScript to make it easier for us to debug and find issues right at compiled time.
Functions
One of the more powerful features in TypeScript is its ability to help us define functions. Let's take a closer look at some of the features that we have. We've already seen how we can set the parameter types to be required or optional, but we can also use things like arrow function expressions. Basically, these are like lambdas in other languages where we can create a compact form of the function expressions. It allows us to omit the function keyword, and the return basically for the values, and we can scope the contents of the function with the "this" keyword. We'll take a look at a couple of examples of these and how it's really useful. There's also a keyword with functions called "void," so if we have a return type that has no value, we can just specify "void" with our typings. We might have a function called "myFunc" and here we can see we've got it defined to have two parameters with h and w both number types, and it's going to return the calculationable for those. Another way to write the same function is to define it with the same parameters but instead of doing return inside of a body of the function, we can use the arrow function. So here the arrow function is going to return h times w and it's going to omit the function keyword, and then we can get rid of the return statement. And the shorthand syntax can really help us out as we define larger functions and objects with collections of functions on them using interfaces as we'll see in the next module. It's really important to keep in mind that the TypeScript functions and all the typings that we have always emit the same old JavaScript, so both functions up top here in TypeScript will emit the same function in JavaScript as shown below. Now, the void keyword is going to let you specify the return type that has no value. So if you wanted to find a function that's not going to return anything, maybe it just does some internal calculations and sets some variables and that's it, then you can use void. So here we're creating a function called "greetMe"; it's defined as a function where it's got a parameter called "msg", and it's -- that parameter is a string and it's going to return nothing. It's not going to have a return value. So no return value is there, so the function might be defined as something like this. We've got greetMe, it accepts message, and then it's going out just print out to the console log the message. So we could call it simply by saying greetMe "Hello!" Let's take a closer look at functions and go write some code.
Arrow Functions and Debugging
Let's create a few functions that take advantage of optional parameters, the void return type and arrow function expressions. First, we'll create a new file inside the Scripts folder and it'll be a TypeScript file and we'll call it "2-7-functions" and we'll get rid of all the TypeScripts that have been put in there by default, and let's create a simple function that's going to square some values for us, so we'll call it "squareItSimple," and all we want to do is make this function accept two values. We'll make it accept h and w, and we're going to have it return out the result of those. So we'll do an h times w, and that's all we want. That's some basic JavaScript, and notice that the TypeScript on the left is the same as the JavaScript on the right, it's because we didn't use any of the typings that we have been learning about. So we could simply go in here and say, "Look, we're going to protect ourselves and make sure we're passing in the numbers, so we'll make sure h and w are going to use numbers. Now, that should also automatically give us a return value for squareItSimple to be a number. Notice it accepts two numbers and outputs a number. We could go one step further even and make it a little bit simpler and we'll call this one simplest. We don't actually need the function keyword here either because it knows that there's going to be a function here. So now we've got the same thing again, we've just omitted the function keyword. Now, if we look at the JavaScript, it should be exactly the same for all three of these other than the name of the function, and notice that it is. Quite cool, huh? Well, now let's take advantage of optional parameters and do a different example, so let's create a function called "helloWorld" -- got to have one of those, right? And then we've got a parameter called "name" and we're going to say question mark, it means like name, it's optional. So we've got name being optional here and we're going to tell it's going to return a void. So this function is going to accept the value optionally which will be a string, and it's not going to return anything to the user. So we define helloWorld, then inside it really doesn't matter what it's doing as long as it's not returning a value in this case. So we can say "Hello" and we can pass in the name. Now, because the name is optional, we might want to check to make sure the name is there. So we can just say name, or if it's not there we can put something in like "unknown person." We can call helloWorld either with no parameters or we can call helloWorld with a parameter in here, of somebody like John. So we hover over helloWorld again, we can see here it's going to basically accept the parameter value if we want to and then not have any return value because it's using the void. So now we've seen here where we can have optional parameters, we could see where we have a void where I don't have return type. We've also seen how we can use the arrow function for return types as well. It's actually inferring the return type here as being a number because it's a number times a number. But what if we wanted to do more complicated parameter values, something like passing in an object literal? Well, let's take a look at that. So in this example, let's create another function called squareIt, and in squareIt we're going to simply just get something called a "rect" which should be rectangle, and then we're going to pass in h and w again. So we're going to have a number for the first one and we're going to pass in w. We'll make w optional in this case. So now we've got the w and we just wrap up our object literal. So we're going to pass in this object literal right here and then, we're going to tell that it's going to have a return value of a number. So there we've given our definition for the function and I'll pull it down to another line so you can see it. So we've got our function here called squareIt which is defined as a function, which accepts a parameter called rect, and that parameter must be an object which has a property called h, which is a number, and may or may not have another property called w which if it does will be a number and it's going to return a number. Well, let's create a couple of rectangles now. So we're going to have rectangleA and rectangleA is going to have a height of seven and it's not going to have any width, so basically it's going to be a square. And then we're going to have rectangleB and we'll give that one a height of seven and a width of 12. Now we can go ahead and define squareIt down here and we're going to say, "All right, create this function and this function is going to accept a rectangle parameter." Let's put the logic in, there we go. So now we have our squareIt function which is accepting this parameter and it's going to assume that rect is going to be one of these guys up here, basically is going to be something that has an h and optionally a w, which we're good to go. And then we can simply just call this by creating some values, so we could see with something like consolelog and let's print out in this case a value from squareIt and we'll pass in rectangleA and then we'll just repeat that for rectangleB and we can see what happens in the console window. So we'd have a couple of things in the console window right now. So far we've got the helloWorld with the default message and then we've got helloWorld with John up top and we'll comment those out real quick, and then we'll go down and just do the two rectangles. So let's go find the 2-7 functions view and let's run that in the browser. And notice we got a not a number and 49. Now that's a problem, so we must have some kind of logic error, we can come back here. And I know there's a logic error but what we can do is we can actually set a breakpoint on this line. And this is inside the TypeScript. Now, one way you can set breakpoints in here is by going into Tools, go under Options and if you install the Web Essentials plugin that we talked about earlier, under TypeScript you can see Generate Source Map. You set that to "true," it creates a source map file and then you can then debug and set breakpoints in your code and that'll work in IE9 or 10, or any browser that supports source maps. So here we have the breakpoint set and I could press Run, click on the arrow functions and notice it jumps right to the breakpoint. So I can see rect has been passed in, here's my object, and notice the handling has an h, there is no w there; so w is undefined which is heading this clause here. I can then just step right into the function or step out of it, we'll just go right through it. Now here we're saying, all right, calculate h times undefined -- oops! See, I've got my logic backwards. I wanted that to be not equal to undefined. So it's very simple to do, now I can just stop the code, I can come into my breakpoint, I can save that, I no longer have to run that breakpoint. I can run it back in the browser by pressing debug. I can click on the arrow functions and if you'll notice now, when I refresh the cache that I've got 49 and 84 -- everything worked perfectly. So debugging is one of the nice features that you get right out of the box with TypeScript in Visual Studio, and that's really been enabled by the source maps. And you can see those over here on the right-hand side. We have a TypeScript file, we generated the js file for JavaScript on every save. So every time I go down here and I press "Save," it's going to regenerate the file on the right-hand side, and then it's going to generate the source map file because of the option that I have in Web Essentials. And debugging really came in handy in this case and I highly recommend that you take advantage of it. Now, let's take a little bit closer look at what we can do with interfaces with functions because we've been defining functions so far right in line like this, but that kind of gets messy. So we can use an interface to actually make this a lot cleaner. Let's take a look.
Functions and Interfaces
Now let's create a couple more functions and see how we can use interfaces to really clean them up. So let's go and create a new file and we'll call this "2-8-interfaces" and let's make a little bit of room so we can have more room to type. And first, let's create a function without any interface; we'll just create one called "squareItBasic." And we want this to be a function that accepts a number and then it's going to return number times a number. So whatever you pass in it's going to multiply it and return it out. Notice in the definition it's using type inference to figure out the return value is a number, but I didn't tell it what the parameter was coming in. If I did that, I could simply do number right there. Now, you can see it accepts a number and returns a number. Pretty easy to do. Now, what if I wanted to make sure I could reuse this and make sure it follows a certain pattern? So I could create an interface and I could call this the "SquareFunction," and let's go ahead and define this as having some value, being passed in which is a number and then asked to return a number. So we're saying this is an interface and we're going to accept a parameter called x, which will have a number, and that it will return a number. So let's get rid of the number parameter down there and all we have to do to make sure this guy here follows that interface is just say, "All right, let's set squareItBasic to use these SquareFunction interface and it will tell us right away if we're okay." For example, if I did something that was out of the ordinary, like let's say I passed another variable like "foo," then it's going to tell me right off the bat that, "Look, you're not following the interface. You can't convert this one to that one because it's expecting different parameters." So we can get rid of that foo parameter. And that's a very, very simple interface. Let's go and take a look at how we can fix up the rectangle example we did in the previous sample using interfaces. Now, let's go fix up the rectangle sample we did in "2-7 functions," and I'm going to go open up the folder or the code that we already wrote, and then I'm going to grab all the code for the squareIt starting here at line 19 all the way down to the bottom where I could write them out in the console. So we're going to ahead and copy those over and I've got squareIt right here. Remember all this code that we wrote to say, "Here's a rectangle. That's going to be the parameter that we pass in with the height and the width or the width is optional and it's going to return a number. Wouldn't it be nice if we could run an interface to do this?" So here we can take an interface for the rectangle and we're simply going to define the rectangle interface to have h and w. And in the interface we can define optional parameters, too. So we've got an optional property here for w and h is mandatory. So what we could do here is now say, "All right. We're going to have rectangle right there, it's a new parameter, and it's going to be of type rectangle interface and it's going to return a number. Much cleaner, isn't it? So now we've got this code instead of saying, "All right. We could put the full code up here," instead of saying, "Down here, we have squareIt with all that code." So it's just a little bit cleaner and it's much more reusable, so you'd be using this interface in this case. But let's go ahead and take a look at another example which allows us to combine several of the learnings that we had so far. Let's create an interface called "Person" and we're going to give this a couple of properties. So far, I've given it a name and age and kids properties and I've also given a property for calculating the pets. So now, we've got our person interface right here, and we can define an object based upon this person if we want to. So we can define p down here and we can create him and say, "Look, he's got to follow this person model," and then when I do p. you're going to see those properties popping up here. If I do calcPets, you're going to notice it's going to have a return value of a number. If I do age on here, then we can set that equal to nine, or whatever else you want to do. If I try to set it to a string, it's going to tell me, "Look, that's not the right person that we have." So, what can we do with this kind of an interface? Well, let's map it out a little bit further first. Everybody wants a function called "makeMeYounger," so let's go ahead and create a "years" parameter so when you pass in the years, I'm going to make you that many years younger (chuckle) than you were. Now, we're going to take the void on this case, so we're going to make you younger. So if you pass in seven, I'll make you seven years younger, but it's not going to return anything. And let's have a greeting on here. Every person needs to be very friendly, so we'll have a greeting that we can pass in, and when we do that we get back a full greeting which will include their name. So now we've got different properties on the person interface; we have name, age and kids, and one of them is optional. And then we have a function for calculating pets which returns a value, makeYounger returns nothing, it's going to operate on the age internally, and then greeting is going to use the name property and then output a string. Now we can take the person and we can implement it and we simply do that by creating an object literal, and inside here, now it's red because it's not actually implementing the interface yet; we're missing all sorts of properties. We can say the name is going to be, let's make it "Colleen," and I can set the calculation of pets to be a function (typing) and we're going to say, "How many kids do you have?" (chuckle); we can do this kids times two, that's how many pets you're going to have. So every kid gets two of them. And notice here I try implement, the full interface for a person using the same format and structure that the interface has up here, all the red lines go away. If I change one of these, like let's say I made the message for the string be something different like a number, we're going to validate the interface that we have, so it's going to say, "Look, you know, it's incompatible in this case." Or we could add an additional parameter to this. If I add another parameter here called "foo" and I made it of type any, it's going to tell so we don't have that same interface implemented. We have to implement the interface for Person up here. Now, we can add other features in here, too, so we could add another property like "favoriteMovie." And notice we didn't invalidate the interface. We still did the minimum interface of what the properties are up here, so favoriteMovie, "Lord of the Rings," not a problem. So if we want to, now, we can examine this p object. We could use something like create the "pets" variable and we could do p.calcPets and we can pass in nothing to pets because that's what it expects, and then we can console log it. And let's go ahead and make myself a little bit younger here -- actually, make "Colleen" younger. We'll be nice, we'll take 15 years off her. And now we're going to say, "Go ahead and get the new age." We'll get a new property called "newAge," and let's also go ahead and print out a greeting. So notice now we can use all the different methods and properties that we have inside of our Person object. calcPets gives me the IntelliSense to tell me that there's no parameters coming in and it's going to return a number, so I can then perform operations on it. I could say, you know, the pets times 9 if I want to, or plus 8. Can't pass in parameters to those because those parameters wouldn't -- it would invalidate the signature of the function up here and then only -- then I have to change the value up here so I could post in num here and make it number, which should then make this code right but then this code is wrong because it's no longer following the interface that I have up top. So I have to get rid of that, and once I find the interface is working, I can get my code back again. Now, makeYounger is going to pass in 15 for the years and then it's going to take that and it's going to reduce the age. And notice the context that we have for this function. We have this keyword and that this keyword is going to represent the p object. So therefore on that object, I can go ahead and use the h property which will be for the person. So it's going to reduce that and it should print out 25. So we're expecting here for our pets to be 8 because we have 4 kids times 2 pets, and then when we make makeYounger it's going to change the age from 40 to 25, so I should put that into console; and then which should say, "Good day to you" and then the name of the person, "Colleen." Let's take a look. We'll go ahead and run this by clicking on two interfaces and we'll view it in a browser. And notice we have here, our values to the squareIt, then we have our 8 pets. We have our 25 for Colleen and then we have a message printed at the bottom. Very simple to do. And you can still set breakpoints inside of here very easily, notice I set a breakpoint there. Again, I can go up to Tools, Options, go down to Web Essentials, TypeScript, set the source map to true and that's going to automatically generate the source map file for us, and that actually sets the source map flag on the compiler. And once I do that, and I save, if you look over on the right-hand side, you're going to see the interface's js map file which is going to be used to help debug it. So now, when I click on browsing and I go into the basic interfaces, I jump right inside of the function. And notice I can see the IntelliSense for the value for kids even though kids is not in the function, it's out here on the object called p. So what have we seen here? We've seen quite a few examples on how we can set up functions and use things like void or the return types, or the arrow functions to really clean up our code, and we also saw how we can create an interface to define what our objects look like as in the case down here with the person. But we can also use an interface to define what we return from an object as well. So to save us some time on this one, let's go ahead and flip over to our "Before" folder in the code and right where you see After and Before, you'll see "returning-interface" text file and inside of there you'll see some text. Well, let's go ahead and grab that text and let's go back to our code and let's paste it in at the bottom of the module right above the curly braces here. Now, let's take a close look at this first and we'll minimize the function. So first thing we did is we created an interface called "SessionEval," and this interface is defining a function called "addRating" which will accept a number and then return nothing. We're just going to add ratings to it. And then we've got a function called "calcRating" which is a function that's going to return a number and has no parameters. The purpose of this interface is we're going to find an object that we can use to calculate session evaluations. So as you're scoring the sessions on a score to 1 through 5, it's going to push it into an array and then when you call calcRating, it's going to tell you the number -- sounds pretty simple. So we defined our function now and the function is defined using this SessionEval interface, and then internally we've got over our logic here for how we're going to implement addRating and calcRating and then the key is the return statement. What we've done is we've said, "Okay. We're going to define this sessionEvaluator. It's going to implement SessionEval. It's got to have an addRating method and it's going to call this internal addRating and it's got a calcRating method, which is going to call the internal version. So this one is going to match up with that right there. And then, we can simply just say, "Go ahead and create s," because that's going to equal the execution of sessionEvaluator, and the reason I'm executing that is because by executing it I'm getting the return object and that return object is represented by the interface that we created, this SessionEval. So down here, we've got s which is actually of type SessionEval, and then I can push a bunch of ratings in and then I can calculate it out and print to the console window. Let's take a look at what this does when I view it in the browser. Notice it calculated the rating of 4.75. So this shows how we can use an interface as the return type of an object, and then the previous example we saw how we can use an interface to define what the object itself would have for its properties. The interfaces that we've seen so far have been pretty powerful at cleaning up our code, but in the next module, Dan is going to show you some even cooler ways that you could use interfaces when you're creating things like classes.
Static Typing Recap
In this module, we reinforced that all JavaScript is valid TypeScript. TypeScript isn't a new language. It's just a superset of JavaScript, very powerful that we can do a lot of things with that really clean up our code and make it easier to do compiled time checking. So what do we look at here? Remember, it always emits JavaScript. Anytime we write TypeScript it's always going to end up being JavaScript, so all the browsers here will be able to use it. And we're getting optional static typing. We don't have to opt into them, but if we do, we can take advantage of the different types that we have, things like the numbers or the Booleans or the objects. And we get various types that we can use that all end up being JavaScript. Again, it's just all JavaScript. We also get compile time checking which makes it a lot easier to find issues before you run your code. And then we took a look at how you can use ambient declarations for external references, things like jquery or Knockout, or whatever your favorite library might be; and we can use this with typings or definition files. And if you want to find, if your favorite library has a typing file, you can look at the links on the right. We also took a close look at several kinds of objects and functions in many different variations of them using parameters that required or optional, with arrow function expressions, returning the void value, and then using interfaces to find our functions or objects, or return values from objects.
Classes and Interfaces
Introduction
In this module, we'll take a look at how classes and interfaces fit in to the overall TypeScript language. I'll start off by defining what classes are and how they can be defined within your TypeScript code, and then we'll look at different members that you can add inside of classes. From there, we're going to look at interfaces, define what they are, and explain how they can be used to provide consistency in our code and how they can be integrated into classes. So let's go ahead and get started by talking about what classes are and how they can be defined within TypeScript applications.
Defining Classes
TypeScript provides built-in support for a concept called a class. Now if you're coming from an object background such as C# or Java or C++, then you're already used to what a class is. But if you're coming from pure JavaScript or a language that doesn't support classes, you might not know exactly what it is and why it's used, so I'm going to define it really quickly and then we'll jump in to how TypeScript enables support for classes. So a class really is just a container. The role of a class in TypeScript is to encapsulate code, such as functions or variables, into reusable containers that you can use throughout an application. Now, if you think of it as a container, then a class really is like a Tupperware container. It's just a container that you can throw different things into it. Now, when it comes to classes in programming, though, we want to throw things in that are related. So if I'm writing a car class, I'll obviously put things that are related to cars. If I'm writing an invoice class, I'd obviously put things that are related to invoices. So the different members, you can think of those as like Lego blocks, and each Lego block has a different purpose. And we don't want to just scatter those on the floor. We want to organize them, we want to encapsulate them into this Tupperware container, otherwise known as a class. Now, the good news is, TypeScript support classes out of the box, makes it very, very easy to encapsulate our code and this is really nice, especially if you're working with ECMASCript 5 or earlier; JavaScript just doesn't support the concept of classes. Now, you can emulate it with different types of patterns, like the revealing module pattern or the revealing prototype pattern or others, and I have a whole course called "Structuring JavaScript Code" on Pluralsight, if you're interested. But the nice thing with TypeScript is, we don't have to learn those patterns per se. I can just easily encapsulate my code without really having to know a lot about how it works behind the scenes. So, what TypeScript does is allows us to write our different members. These are our variables and our functions and some other things I'll show you here, and then include those in a class. So if you think of each of these things I'm going to show you as a Lego block that's going to go in the Tupperware container, really a function just goes into class if you're a little bit newer at this concept. So fields would be variables, these are one of things you'll see that we can put in classes. You can also define constructors. These are used to initialize an object. For instance, you might pass in some starter data that the object needs at runtime. Properties are ways we can get or set different field values. They act as filters as you'll see. And then finally we have the common programming construct of a function, an action that we want to perform. Now, when it comes to defining the class in TypeScript, it's actually very simple. We can just use the class key word, and you can put the name of the class and then put our brackets to start the class and to end the class. That's our Tupperware container. So it's like having a Tupperware container with a piece of tape on it and it says, "Car." Now we can throw in our different Lego blocks that represent the members for that Car class, and these are the fields, the constructor, the properties and the functions I just talked about. So, here's a simple example to get us started of a car, and you'll notice that inside of it, first off we have a field here called, "Engine", which is a string. We also then have a constructor. Now what we're going to do with the constructor is when somebody creates a new instance of this car, we want to allow them to pass in the actual engine type as a string and then we're going to store that up in this engine field. And so this is the field, and then obviously this is the constructor, and those are two of the four members that you'll see in TypeScript classes. Now, the constructor itself is not something that you have to have in a TypeScript class. In fact, you can just leave it out if you want but it is useful in these scenarios where we want to initialize the class with some data. Now, here's another example that simplifies this class and really just kind of provides some shorthand notation. In this example, you'll notice that we have public engine which is a string. Now up here in the constructor we just had engine which is a string. What the TypeScript compiler will do is when it sees the word public on the front of engine; it will automatically generate this field for us. Therefore, I don't have to go in and actually type it out, I can just work with it directly and it's kind of nice if you want a short cut way of generating. Now, some people may look at this and say, "No I'd rather explicitly see it." That's fine but if you don't and you put public, it'll automatically generate this engine field for you. Now, of course functions are really what we're after here, we need to store data in variables but at some point we have to perform some actions. So here's a simple example of two functions. Ones called start, one's called stop inside of this TypeScript class called Car. And you can see that in addition to the field, the constructor -- we then have these two down here and these are their functions. Now, these functions need a reference and this case the engine that was originally passed in to the car when it was new natively, when it was created at runtime. To do that or to get access to that engine, you'll notice that I have to prefix it with this and you'll see as I do the different demos, this is a very common theme in TypeScript. It gets us access to this instance -- engine field in this example here and so you'll be seeing that more and more. Now, in addition to fields, constructors and functions, you can also wrap fields in what we call a property. Now if you're coming from a C sharp background, this will be really something you're used to or even if you're just coming from a normal JavaScript background, this is something you can do in newer versions of JavaScript. What TypeScript supports is the ability to say how we get the value from a field such as our engine up here and how we set the value of a field. So they really are filters into a field. Now by default, your fields in TypeScripts are always public. In fact all your members in a TypeScript class are publicly accessible. Anybody can get to them. If I want to filter the data that's added inside of a field such as engine error, then I obviously don't want to worry about somebody getting to it directly. They should have to go through the filter to do them. So to do that, you'll notice how you use the get keyword and the set keyword and then I simply give it a name. It almost looks like a function but what will happen behind the scenes is TypeScript will use property functionality to actually generate what we call a getter and a setter. So in this case you can see that we say, "I would like to get the value of engines," so we just return this underscore engine. Now I marked it as an underscore to just a convention I like. It's actually pretty popular in JavaScript. Any time something is private, you can put and under score. But in TypeScript because everything is public by default, I need to explicitly say, "Hey, this is private," so that others can't get to it. They have to go through my get accessor here. Now when they go to set of value into this that my setEngine here accepts the value as a string they'd like to set and now I'm going to do a little filter. Now this is a very simple example, but you can do more complex business logic if you'd like to make sure that the value being added is the appropriate type that you'd expect. So in this case, I'm saying if the value they pass in is undefined, I'm going to throw an exception, supply an engine because I need an engine for my car. If there isn't an error, if the engine is valid, then we'll go ahead and assign that value up into our private field which is our Underscore Engine. Now, we can also define complex types and use those inside of classes. Now a complex type is just a class that has its own set of members inside of it. It could be fields, it could properties, it could be functions. You'll notice in this case, instead of doing a private engine that is a string as in the previous example, I have a class engine up here with its own constructor. It's going to generate two public fields; one is horsepower, the other is engine type. And we talked about this earlier; this is the short cut or shorthand notation in TypeScripts for generating the fields automatically. And so what will happen is now, when somebody creates an instance of a car, they'll pass me the engine. I'll then assign it up into the private variable here. Now, we might also go in though, if we have some properties down here, then you'll notice that I'm not actually assigning that to Underscore Engine. I'm assigning it to Engine. Well, again if we go back, imagine that we have a get in a set for engine so we would be setting the value and then assign it up except for it wouldn't be a string in this case. It would be an actual engine object. So this is what we call a complex type and again, it's not really a new concept if you've worked with object-oriented languages before. But it is something that in JavaScript, you might not have called it that. You might have just called it for instance just an object literal. Well that's a complex type if you will. So now that we've taken a look at that, how do we actually use these classes at runtime to do something? Well we have to new them up, and the way we do that is we use the new keyword. And so first thing I'm going to do is create an engine, and this engine -- I'm going to pass in the horsepower and the type of the engine. And then from there I'm going to pass that engine into the constructor of the car, which then gives us back a new car and we're ready to go. So now that we've seen some of the syntax, let's go ahead and jump in to a demo that shows how we can create classes and add members into classes.
Demo: Defining Classes
Let's take look at an example at how we can work with our car and our engine class so we can add some different members into those classes. So, I'm going to come and create a new project here and up here, we're just going to TypeScript and that will only give me a nice little HTML application for TypeScript. All right. So let's just call this Defining Classes. Now, I don't actually want this ap.ts. So I'm going to come in and define a new one. So we'll add a new TypeScript file, we'll call it Car and I'm going to go ahead and put engine inside of this although you certainly can make separate files if you'd like. In the next module of the course we'll actually talk about modules -- TypeScript modules and show how you can load different files and relate those to each other. All right. So let's go ahead and delete what we have here and we're just going to use the class key word and define a car and I'm going to make it upper case because in JavaScript that's a convention that typically means you have to new up the instance to create an object at runtime. If it was lower case, it's more of a singleton and I wouldn't have to new it up per se. I could just call it directly. All right, now I'm also going to come above it and we'll create a class called Engine and same thing, I'm going to make an upper case. Let's go ahead and save that and what this will do is now notice the JavaScript through the Web Essentials plug-in which is generating this, it's showing me that we have an engine which dereferences the function that's self invoking and then inside of it, it has its own engine object because the function in JavaScript is obviously an object and it would simply return that. That's all we've done so far. So we've made a container, nothing more. Now, for the engine, we can do what we had earlier, we could have different things in that engine but one of the things I might want to have is the constructor that we talked about. So you'll notice that in Visual Studio it turns blue indicating the keyword which makes it easy to work with. And now I can define our horsepower and I'm going to save that horsepower as actually just a number. And we can define engine type and the engine type is going to be a string and that's all I have to put. We're pretty much ready to go. I can close my constructor brackets and that little shortcut syntax for the horsepower anyway, will auto-generate the horsepower field. So let's go save it and take a look at what was generated. And you'll notice that in the engine we have horsepower but you'll notice engine type is not showing up or being assigned and that's because it didn't have the public key word out in front of it. So let's go ahead and add that. Okay, now if we go back you'll see that we have horsepower and engine type assigned to two fields that are just dynamically generated in the JavaScript. So that's what the public keyword buys you as far as the constructor goes and fields. Now, down in the car I might also want to have a constructor. But let's go ahead and say that we want to have in this class an engine of type engine and then we can come in and put a constructor. So we'll say that you passed me in an engine and I'll go ahead and assign it so for any of the proper case there. All right, now what I want to do though is I want to make sure that whatever they pass in is valid. Now I certainly could write some filtering logic right here but let's go ahead and demonstrate properties again like I showed earlier. So I'm going to make this private and call it Underscore Engine, all right now nobody can get to it except for this instance once it's created that runtime of this car. So I could come in and I could do this, but I don't want to do that in this particular case because I want to run through a filter first. So what we'll be doing is I'm going to save this dot engine which we don't have yet but we're going to add. So now what I'm going to do is add a getEngine and the getEngine is going to return an engine. But the way it's going to do that is we'll say, "Return the field." Now I have to put -- to get to it I mentioned earlier that you'll see the word a lot. You'll notice the name engine does not exist in the current scope and that's because it's not available or won't be once the JavaScript is generated. By doing this dot, you'll notice I can get to it because I can get to my own private members, of course. Now, the set looks very similar except for I need to pass in a value which is a type engine. And what I'll do is just a little filtering logic, (typing) so we'll do the same thing I showed earlier. If engine is undefined, then we're just going to throw "please supply an engine" and that will be an exception. Otherwise -- and I shouldn't say engine, I should say value there. Otherwise, if the engine is okay, the value they pass in, then I want to assign it up to the field. And that would be an example of doing a simple property. Now, we could also come in and do functions. So we could have a start. And in this case I'm just going to do a simple alert, and we'll just say, "Car engine started." Engine dot -- let's just say engine type, and that will let us know that we started that engine type. So that's an example of a normal JavaScript function. Now you'll notice, though, it's erroring out. When you first get started with this you're going to have the habit of wanting to always put function, and we're kind of used to that in JavaScript. And if I put this outside, that would actually work fine. I'd have to change this part, but the function part would work. Well, when you're inside of a class, you actually don't put the function keyword you simply just put the name of the function and then you can put the parameters, if there are any, and then what it returns, in this case we would just do an alert. Now, if I really wanted to be specific, I could even do this, and I could say that, start doesn't return anything, it's just void. But if I leave that off, I'm not returning anything anyway, so really there is no harm, but it is good for IntelliSense. So, now let's go into our default HTM and we'll go ahead and change this to car.js. Now, I need to be able to use my car object, though. So I'm just going to put a little script block and we'll just do JavaScript for this, although I could do it in TypeScript, as well. And what I'm going to do is say, hey, when this loads, so when the window loads, we'll do a simple function here. And now I can create a car by saying, "New car," and the car you'll see takes and engine. Now, as I mentioned, I can also do this in TypeScript and get full IntelliSense, though, which is actually really nice. So, I'm just going to throw this at the bottom and we'll go ahead and do a window load. And notice that when I do new Carr it says I get an engine parameter needs to be passed in to the constructor of type engine. So, I'm going to go ahead and make an engine here. We'll save our engine as New Engine and those we get full IntelliSense against our fields and our parameters of the constructor here. So we pass in a number and we pass in a string which is our engine type. So let's go ahead and say it's 300 horsepower and it's a V8 and then we'll pass that in and then from here I'm just going to do an alert on car.engine which calls our property getblock. And we'll say engine type and then if I wanted to see that the other way, we could just say car.start because I also showed it right up here in the engine type. So kind of two ways I can go through the property or call the function which ultimately calls into our private field. All right. So let's go ahead and go back to our page to see that we get V8 and car engine starter V8. So you can see that it did work appropriately. So, that's an example of getting started with classes and some of the different members that you can put in classes including fields, constructors, properties and functions.
Demo: Property Limitations
It's important to note that properties although very convenient, won't work in every browser once the JavaScript is generated. There's specifically an ECMASCript 5 feature and if you're talking about i6 or i7 they definitely won't work and i8, they kind of can be made to work but only with DOM elements or objects. And with the newer browsers they do work. So I'm going to walk through just a couple of got you's here that you might run into if you do decide to use properties and talk about some of the quick alternatives you can do. Now, first off I'm using Web Essentials for this particular demo and most of the demos in this module and so you'll notice that it is accurately generating JavaScript codes that has object.defineProperty and this is a newer function that's available in the newer JavaScript engines out there. Now, this works great if the browser supports it and if you're compiling your TypeScript code using the ECMASCript 5 setting. Now, what I can do is with Web Essentials, it automatically assumes that you're going to be using ECMASCript 5 and so if we go up to tools, options, and if we scroll on down to Web Essentials, we can actually change that. We'll come to TypeScript here, you'll notice that we could say compiled ECMAScript Three and it's false. So I'm going to go ahead and set that to true. Now let me go ahead and save this and now let's take a look at our code and notice that we get an error. It says that we have to target ES5 or greater. Now, what we can do is we can manually either change it back, like I just showed you, or if we were using the tsc.exc, the TypeScript compiler, we could say, dash, dash, target, and so it would look, That's correct. .exe. You could say target ES5, and then you can give it your name of your file, which would be car.ts in this example. And what that'll do is compile it using the ES5 settings. Now the got you here, though, is that's not going to work across browser. So if you're not targeting older browsers then this will work fine for you. But if you are targeting older browsers, you need to watch out for this. Let's go back to what works and we'll go to tools, options, come back in here and for Web Essentials, I'm going to set this to false for ES3 and now you'll see when I save and let it generate. And there we go, and you can see it works, we get our object.defineProperty. So it's just a minor got you, but important if you didn't know about it. So what would we do? Well, the easiest way to fix this is simply put a setEngine and we might have a getEngine and that's what the callers of this class would actually go through. And then we would have to change this to setEngine and we could pass in the engine that we want to set right here, and that's what it would look like. Or if you just don't want to worry about these filters here, then you could just use fields that are public, and those would work as well. So it's something that if you're targeting newer browsers you won't have to worry about, but something that I wanted to put in this particular section mainly because properties are very attractive, especially if you come from a C# type of background, but they're not going to work in every browser. So it's really important to understand that up front.
Casting and Type Definition Files
Now that you've seen how to work with classes and TypeScript, I'm going to wrap this section up by introducing a few additional concepts that you need to know as you work inside of classes. And the first one is casting or converting between types. Now, if you work with C# or Java or another object-oriented language then you're probably used to the process of casting between types. If you've never done this before, all it means is I want to convert from one type to another type. So here's a simple example. I have a table variable which I've typed as an HTMLTableElement. Now this is a built in object in TypeScript and it comes from a library called lib.d.ts which was introduced in Module Two. Now this is a DOM element representing a table obviously. Well if I want to programmatically create a table element inside of a class in TypeScript, then I just do the normal document.createElement and I give it a table. Well, the problem is, this will fail, and the reason is that createElement returns an HTMLElement not an HTMLTableElement. So what do I do to fix it? Well, we need to write code like this, and this is where we'll cast between an HTMLElement to an HTMLTableElement. So in this example, you can see the code is almost identical. We do document.createElement table, but then notice over here, I'm doing a cast. Now this will work. This is the proper way to do it, actually. And what we're doing is simply telling TypeScript, hey, I know what I'm doing. I want to convert between an HTMLElement and an HTMLTableElement. Now, how does TypeScript know about HTMLTableElements or HTMLInputElements, or all the other ones that are included? The answer is Type Definition files. Now these were introduced briefly in Module Two but I'm going to revisit them here because they play a really important role as you start to build more complex classes in code with TypeScript. Now, as mentioned, as you work with things like HTMLElements or HTMLTableElement objects, those are known by TypeScript because there's a lib.d.ts file that's included out of the box that references DOM objects and has definitions for those, as well as JavaScript objects. So for those it kind of just works out of the box and you have this Type Definition file that's there, which I'll show you in a demo in just a moment. Now, if you're doing third party libraries, though, such as jQuery, and this was also introduced briefly in Module Two, then you're going to have to have your own custom Type Definition file. Now there's a really nice site out there on GitHub, and you can see the URL here, and it's called DefinitelyTyped, and this has a very large list of third party script libraries, and it includes Type Definition files for those script libraries. So if you want to work with things like AngularJS or Knockout, then they have a nice list of these and you simply grab that Type Definition file and include it in your TypeScript project and then TypeScript will automatically know about these third party objects just like it does with the HTMLTableElement that I just showed because of the lib.d.ts. Now, before we wrap up the section, let me show you a quick demonstration of how to work with casting and how to integrate these Type Definition files.
Demo: Casting and Type Definition Files
In this demonstration, I'm going to show a real simple kind of hello world type of calculator class, and I'm going to show two ways to do it. The first thing we're going to use is the DOM and then I'm going to show how we can do the same thing but with jQuery all using TypeScript, of course. So, first off, you'll notice that I have a class called calculator and that it has a couple of private variables inside of it and these are going to be used to store some HTMLInputElements and an HTMLSpanElement. Now, where do these guys come from? Well as I mentioned earlier, these are from the lib.d.ts file that's included automatically with TypeScript. So if I right click on this I can say, go to definition, and this will actually take me to the lib.d.ts and here's the definition for an HTML input element. Now you'll note that it's an interface and we're going to be covering more on interfaces later in this module. So that's what the lib.d.ts file does; it actually defines or has definitions for the DOM elements and the JavaScript elements out there. So, in this particular case you'll notice that in the constructor I'm going to pass in the xId, yId and the outputId. Now these are coming from a webpage, and in the webpage, you'll see that I have an xId, a yId, and then I'm going to have an output area where the calculator writes the actual calculation that's performed. So if we go back to this one, you'll notice that I'm just doing the standard document.getElementById, but if we mouse over the getElementById you'll notice that the TypeScript definition says that we get back in HTMLElement. Well I actually want to work with an HTMLInputElement, so I have to cast from the more generic version, or abstract we'll typically call it, HTMLElement to the HTMLInputElement, which is more specialized; obviously that represents an input like a text box. And I'm going to do that in two places here and then I'm going to do the same thing for the span. I'm going to go from the HTMLElement, to an HTMLSpanElement, and that's an example of casting. Now, from here the application calls wireEvents. All this does is uses document.getElementById to add an EventListener. Pretty standard JavaScript here for the click event. And when that fires, this code right here which is an inline function will be called. So we have an arrow function here. The event object will be passed in and then this is the body of the function here, and we're simply going to output the calculation for the X and the Y value that we retrieve. So notice we're getting the value from the text box for the X and for the Y. Now, if they click the subtract button, we're going to do the same thing. We're going to update the output.innerHTML and we're going to subtract the X and the Y values and we have some real simple calculations to handle the addition and the subtraction here. Now, if we run this it's not a very impressive calculator, it's very much a hello world type of calculator, but you'll see that it should work. We'll do 2 plus 2 is 4, and 2 minutes 2 is zero. Very surprising results, I know (chuckles). But you can see the example of casting here and it's an important thing to know about, especially if you want to work with specific DOM objects like an HTMLInputElement. Now, I've also created a JQuery version of this and the jQuery version is going to be actually a lot cleaner and because we don't have to actually worry about so much of the casting. Now you'll notice though up at the top, I have this reference. Now if I were to take that out, all I did was I went out and found a jQuery Type Definition file and I'm going to show you the DefinitelyTyped website in just a moment. But I included the jQuery Type Definition file, which you can see is jQuery on eight.d.ts and you just drag that into the top of the class file. Now what that does is now objects like jQuery are going to be known, in fact we can actually go to the definition for this it'll take us to the jQuery Type Definition file, and this has all the definition for Ajax functions and HTML and everything if you do jQuery that you would need to know about. So, when we go back, this really cleans things up, especially if you know jQuery, because now I can just take the Id that was passed in, do an Id selector, no casting required because the Id selector returns a jQuery object. Same thing for the Y and the same thing for the output. Now, the wireEvents just changes a little bit because now I can use the shortcut jQuery function click event function and then here's my callback function right here. I get the event object and I'm going to update the outputs HTML and we're going to add the X and the Y and then same thing for subtract; we'll subtract the X and the Y. So, that's an example of not only casting but also the lib.d.ts which has all the DOM and the JavaScript objects in it as well as the jQuery one. Now if you're going to be working with these, you might want to go the DefinitelyTyped site. So if you just head off to Google or Bing and type in "definitely typed" or the URL I showed earlier, you can go to the GitHub site. Now what the GitHub site has is all these different script libraries. So I went in, in this example, and I grabbed this guy right here and then I simply copied this file into my project and then I referenced it in my .ts file by dragging it in to the top of the file, and this has all the definitions for jQuery. Now, it also has a lot of other popular libraries out here. There's Backbone, there's lots of jQuery variance. We have Knockout and many others if you're interested in taking a look at these. So this will likely continue to grow over time as Boris, who is the main contributor here, you can see, and others contribute to this particular library. So it's a nice resource to know about. So, that's an example of casting and working with Type Definition files in TypeScript classes.
Extending Types
Many of the popular programming languages in existence support the concept of inheriting or extending types, and this is the process of writing a base class and then inheriting the functionality from that base class to make a child class. Well, JavaScript doesn't (inaudible) support, at least with ECMASCript 5 or earlier, the concept of inheritance. However, you can do it with something called JavaScript prototyping, and this is a way we can actually take what an object does, grab that functionality, and extend it with another object, a child object. Well, TypeScript allows us to write more what I'd call traditional object-oriented code for inheriting from one object to another and extending a base type. And that's what we're going to talk about in this section, is how do we write a class and then inherit the functionality that class may provide and extend it, add new functionality into it. So, the process of extending types and TypeScript is actually quite simple and very easy to use, as you'll see. If we, for instance, had an auto class and it has some base functionality for maybe the base price of the auto, the engine and other features that an auto might have, we can then inherit from that auto to make a truck or an SUV. And so we can extend the auto, add new functionality specific to a truck and add new functionality specific to an SUV and we can do that very easily in TypeScript without even having to know how JavaScript prototyping works. The extension that happens here will cause the TypeScript compiler to automatically generate the prototype code. So that we get this inheritance functionality without really having to know how that works in JavaScript. TypeScript obstructs that away from us and we just write a very comfortable syntax to extend the class. So, here is what it looks like, in TypeScript. There's a keyword called extent and this is the same as inherits and what it allows us to do is if we had a child class and we'd like to extend a parent class. So the parent class has some base functionality, we want to use that but we want to add to it. We want to extend it, then we simply put the TypeScript extend keyword as you can see right here. Now, inside of this child class we can optionally put a constructor. You certainly don't have to have a constructor. But if you wanted to have one, then you'll need to make a call to the base class's constructor. And the way we do that is by calling super. Now in this example, our constructor takes no parameters and our base class takes no parameters in the constructor. So we just put and empty parenthesis on super. But in other examples, you'll see we might actually pass some values to the constructor of the base class. And this will be an example of a child class constructor then calling the parent class constructor. Now what's nice about this is the syntax is very simple you can see. We simple put extends and then to call constructor we use super to call this parent class constructor. You don't have to know a lot about prototyping or in fact, you don't have to know anything about it if you don't want, although I personally would recommend that you do learn about JavaScript prototyping. Now here a little more robust example of the auto and the truck. So we have a class called auto which has an engine, which has a complex type another class nested called engine. And you'll notice in the constructor we can pass in an engine and then we simply assign it up to our field here. It's all a very basic class. Well, what we can do is we can write a truck that extends auto and what it might do then is we don't need to re-do the engine of course because auto-RV defines that. But it might add four by four capabilities, off-road capabilities for a truck. Notice the constructor for this particular truck now takes an engine and a four by four to (inaudible) and what we're going to do here is we need -- if we have a constructor to call the base class which is our auto constructor and we do that again using the super call. Now in this case we only have to pass engine because that's all the constructor for our super class takes. And in this case, we'll pass up the engine and then we're going to assign our four by four that was passed in to our truck constructor, to our field and this will be an example then of a truck deriving from auto. And we have this base class call to the autos constructor, very simple to do. Don't have to write a lot of code and the JavaScript that's generated is definitely more complex. And I'll show you that as the demos move on here. So, let's jump in to a demonstration of how we can work with type extension in TypeScript.
Demo: Extending Types
Let's take a look at an example of how we can extend a base class. So before I show that, let me show the different classes I have in the sample project called type extension. So, first off you'll notice I have an engine class, an accessory class and then an auto. Now the engine class has the constructor that we saw earlier with two fields that will be generated because of the public keywords. But then it also has a start and a stop and these two functions allow you to pass in a callback function and we're going to simulate that it takes one second, 1,000 milliseconds to start or stop our engine. And so notice that the callback instead of the parameter having a type such as bool or string such as these right here, instead this is a callback function. Now it returns nothing, that's what the error void here means. But it's going to have to accept two parameters, a boolean and a string representing did it start it successfully and if it did what was the engine type that was started, V6, V8 whatever it may be. So, that's an example of how we can actually define a callback function and have it be strongly typed in our TypeScript code. Now, when this start is called, we're going to invoke our set time out which will run a timer one time and it'll fire after 1,000 milliseconds and then it's going to invoke this callback function that will be passed in, past the boolean and past the string the engine type. Now, in this case we're assuming it always works for the start or the stop but that might be some more advanced logic in a real lap. Now, the accessory is pretty simple. The constructor is going to create two fields accessory number which is a number and title of the accessory which is a string and then we get to our base class. So this auto is the base class that we're ultimately going to extend and you'll notice that it has two private fields, base price and engine in three public. Now, the constructor is going to allow the user of this class to pass in the base price, the engine and the make and the model and then notice that we're not assigning the engine and the base price directly. We're actually going through some properties. Now we've already covered properties. So I won't go into them again here. But just a real quick note -- you can see a get and a set for both base price and then for engine and then they just have in the set block a little bit of logic to make sure the data is what we want. Now, other than that we have a way to calculate the total for a given auto, we have tax rate and we'll take that times the base price and then we have a way to add accessories into our accessory list and this actually uses a special type of parameter called a rest parameter. Notice it has three dots on the front of it and if you come from the C sharp world you might have heard of the prams where you can pass multiple items simply with a comma between them. This is the same type of thing. It's an array behind the scenes but from the end-user standpoint when they call add accessories, they can now pass in an array of accessories. So we can say new accessory and then pass in the constructor comma another accessory and then we have to pass things in the constructor and then so on and so forth. And we don't actually have to create an array. We just separate our different values with commas and that's called a rest parameter and it's something that TypeScript supports with this triple dots syntax here. Now, aside from that we have a way to get the accessory list, any items that were added. We just return a string and that string will represent the sunroof or whatever it was we added into the auto. So that's what our base class looks like and let's say that we'd now like to come down and extend it. So I'm going to come in here and we're going to say, let's make another class, and we'll call this truck and I don't want to type all this code over again or cut and paste it, that obviously wouldn't be a good way to go especially for maintenance and reuse, so instead we can just extend it. So we'll say extends auto, and just this alone is not going to generate some new JavaScript code that is unique to the extends keyword. So if I slide over the code that's generated at the very top, you'll notice this variable called extends has been added and it ultimately it calls a function that passes this D and B parameter which will explain it -- I'll explain in a moment. But what we're going to do is, we're going to take whatever the base class is, we're going to assign its prototype to the child class that's going to extend our base and then we'll ultimately create a new instance of that for the prototype. So, this will simulate inheritance and this is how we do it in the JavaScript world. Now if we look down, we'll find our truck right here and notice that truck is assigned to a function that takes a super. Well that is what the self-invoking parenthesis will pass in the base type I would like to extend. So it's going to pass in an auto a super. It'll pass truck in and auto in that goes back up into here and that's going to take the second one is the -- in this case our auto, it's going to take the auto's prototype, assign it to the truck prototype and then new everything up. So, that's actually all the code that's being generated behind the scenes to support inheritance because inheritance is an actually native keyword or there is no extends type of keyword like we're doing here with TypeScript. You have to write a little bit of extra code with TypeScript to make it work properly. All right. So that's pretty nice because there's that code and then there's the code we actually wrote in TypeScript which is much easier you can see, a lot easier especially when it comes to maintenance. Okay. So now what we can do with the truck is we can start to add whatever we'd like that unique to the truck. So let's say that I wanted to come in and for instance add a bed length, trucks typically have beds. So we'll say there's a length that is maybe a strength, we might also want to say if it's a four by four and we'll say this is a (inaudible). Some trucks have four by four off road support. Some don't and then we might want to come in and make a constructor. And what we'll do in the constructor is pass in the bed length and the four by four but I'd also want the engine and things. So what I'm going to do is actually grab all of these guys from up top here because we still would want to pass those in when we create a new instance of a truck. And what we'll do though, I mean wrap these so we can see it a little bit better, is we'll also add in the ability to pass the bed length and that will be a string again and the four by four which will be a boolean. Okay. So this is going to be the constructor. Now you'll notice that it says a little air here comes up and it says constructors for derived classes must contain a call to the class's super constructor. Now the super is the auto which means if I have a child constructor in a child class, I have to invoke the base class, the parent class or the super class's constructor. So we do that by calling super and the super is going to take the different things that need to be passed in for the auto. And so I'm just going to assign the base price, the engine, the make and the model and those will be passed up to the super because those are the things if we go back to our auto constructor that we want to be able to pass in here. Now, that's going to handle a sign in those and call in the properties and things, it's going to make it very simple for us. Now the other ones, the bed length and the four by four I want to do myself. Of course, we'll say this .bedlength equals the bed length and the four by four equals the four by four parameter and that's it. All right so now instead of creating a auto and we would new it up and then call the constructor here. Let's change this to create a truck and you'll notice that right off the bat, we get an air because the supply parameters obviously don't match with the number of parameters up here. We're missing bed length and four by four. Let's go ahead and pass those and let's say that the bed length is able to say long bed and for the four by four we'll say true. Okay. So now we've created a new truck and then we can see if this works by calling truck and we can call in the end of the engine. Let's also do an alert on the bed length. Okay. So over here on the HTML file, you can see that I've already referenced the auto JS. So let's go ahead and run this real quick. All right so there's the engine type of our truck and it's a long bed. But you can see that the inheritance did work properly and in fact, we can even then do an alert on the price. So let's call it truck. And notice that I get calculate total which returns a number. So we'll say two strings. All right and we inherited that obviously from the auto, which just makes it really nice and clean for my truck. And now we get the engine type, the bed and the price including the tax for this particular truck and that was calculated based on the base price I passed in. And so that's an example of how easy it is to extend and also the type of JavaScript that actually get generated here as we work with the extension and the prototyping in the JavaScript code that will ultimately run in the browser. To wrap this up, let's go ahead and use some of the other functionality that our base class had with auto, such as the rest parameters that you see here. And we can also play around a little bit with the callback for our engine. So let's go ahead and move on down and in the unload here. We'll take this out and what I'd like to do is say for this truck I want to add some accessories to it. So we can call add accessories and that was inherited from the auto. Now, this was the rest parameter I told you about and we see the triple dot that you see right there and behind the scene is really an accessory array but instead of me as the user of this having to create an array upfront, I can actually just pass accessory com, accessory com, accessory com, accessory makes it very convenient and easy to use. So we'll say new accessory and let's say for this accessory we just want to do some number and the title is some rough. Okay, now I can just put karma and do another accessory. So we could say new accessory and we can do some other number and let's say that we had the towing package and that's an example of actually using the triple dot syntax for the rest parameter we call it officially in the TypeScript world. Now, in addition to adding the accessories, let's say we want to call the engines start function, well we can say truck -- this will get us into the property for engine, we could say engine. And now we can see a start here. Now the start that I mentioned was a callback and so it tells us here that we need to give it a callback function and that callback function must take a boolean and strength. Now, I could come in and just make a separate function if I'd like we can just call this callback if we wanted, in passing something a boolean a strength or I can come in and just do a more inline what we call arrow syntax or an arrow function you'll see, it's an inline nested function. So, we know that this guy needs two things and so the callback is going to be a function that's going to take two things. So we're going to pass in a bool and strength, we'll say that this one we'll call the parameter the status which is a bool and then we'll say that the engine type we'll just name it the same is a strength and when that gets called, here's the body, and I'm not going to do anything too fancy here, but we'll just do an alert on the engine type, and we'll say, (typing) "Engine type was started," something like that. So now what we have done is, when this called, we have to give a callback. So here's my callback parameters, inline nested function. Notice that I don't have to explicitly say function, though, like we would in JavaScript. And so I'll just list those. This will separate our parameters from the body and then the body will actually alert us, and hopefully show the engine type here. So let's go ahead and run that now. (Pause) And there we go, V8 was started. So you can see that it did work appropriately. So that's an example of how we can go in and not only use extension, features of TypeScript, but also how we can use rest parameters and even work with callbacks in TypeScript.
Using Interfaces
If you've ever had a set of objects that needed to implement similar behavior across the objects, such as they all have a start and a stop function, then one way you could ensure the consistency is to use interfaces. Interfaces are code contracts, and we'll talk about what that means a little bit more here if you're new to interfaces. One of the nice things about TypeScript is it provides excellent support for interfaces, which is very useful in a variety of scenarios. So let's jump in and first talk about what are interfaces. So an interface is really just a code contract, but if you haven't ever worked with interfaces before that may not make a lot of sense. So let's do an analogy to a factory. Let's say we have a factory that produces engines, and these engines are physical engines, you can look at them, and on each engine there's a green start button and a red stop button. So any engine you're given outside of this factory will always be started by pressing the green start and stopped by pressing the red stop. And I think you'd agree, that's a very consistent visual interface. Now, what's nice about that is if a new engine comes out, I don't have to retrain the people that start and stop the engines; they just can push the same buttons even if it does something totally different than what they're used to with a given engine. Now, instead of thinking these as visual engines, as you can see with the square or the rectangle and the triangle and things, think about these as being classes. So we have Engine 2 as a class and Engine 1 as a class, and Engine 3 as a class, and they all need to have a start function and a stop function. Well how do we enforce consistency across all of those classes? And the answer is, of course, we use interfaces. Interfaces provide code contract. So we can define an interface that has start and stop, and then these three classes can then implement that interface. Now if they forget to put the stop, as an example, then it's not going to work right and the TypeScript compiler is going to fail, and that's what interfaces buy you, is they provide consistency and if the class doesn't live up to the code contract and do exactly what it says, then it's not going to compile properly. Let's take a look at how we can now define and interface, then. So an interface is defined by using the TypeScript key word called interface. So if you've worked with other languages that use interfaces this won't really be a surprise to you because it's very common key word, but this is what we'd be using in TypeScript. So in this example we're defining a code contract by making an interface called IEngine. Now in this example IEngine has two members inside of it and those members are called start and stop. Now these are the two functions we want any class that implements this interface to have. This will provide our consistency across our classes. So in this example we have the start and stop, they both take a callback. Now the callback, which we saw in the previous section of this module, really is just a callback function, it's not primitive like a number string or a boolean, and you can see that the callback function must take a bool and a string as a parameter and its void; it doesn't return anything. And then start itself is void. And then stop itself is also void. So this is the return type of start and stop. This right here, the void here, represents what's returned out. So here's an example that kind of breaks down what I just said. So we have an interface called IEngine. It has a start function which takes a callback function as a parameter. So the start accepts callback as the parameter, but callback is not a primitive like a string, a number or a bool; instead it's a callback function. And you'll notice that start itself doesn't return anything at all. But callback must have two parameters, bool and string, and it doesn't return anything either; it's void. And that's exactly what we're doing with the callback here. Now, I can define more primitive functions as well if I'd like, just normal like a stark with a string and a string, as an example, and I can even define fields. So let's look at how we would do fields. So here's another interface called IAutoOptions. Now this one only accepts fields, as you can see, but we could certainly add functions as well, if you'd like. Now there's three of them that are required, engine, basePrice, and state, but with TypeScript you can actually make the variables optional. So make, model, and year in this case are optional type of parameters. And what that does for us is, now, anyone that implements this interface, has to have engine, base price, and state, but make, model and year are something they can exclude if they'd like. So it gives us a little bit more flexibility. Now, what do you do with the interface? Well, once you've defined an interface, a class needs to implement that contract, and the compiler will enforce the contract and make sure that you implement all the members of the interface. So the way we do that is we use the implements keyword in TypeScript. In this example we have a class called engine, it implements IEngine, and we know that IEngine has start and stop. Well, that of course means this class must have start and stop, and the signature of the return and the parameters must match up. In this case we have our little callback scenario that we saw earlier. Now you'll notice here that I didn't explicitly put call and void. I certainly could go in and do that. Now, once you have an interface defined, you don't have to implement it. You can also just use it somewhere in a class. So here's an example where engine is defined as a field but we're saying, you can pass me anything that implements IEngine. Now this leads to polymorphic behavior. In other words, we have a set of engines, all implement start and stop, but the way they start and stop may be different and that give us polymorphic behavior. We also have in the constructor the ability here to pass in some data object that implements the IAutoOptions, and that had the make, model, year, and things like that I just showed you. Then we're simply going to assign those up into our fields. So those are examples of how we can use interfaces not only just on classes, like we did with the engine, but also in classes. And it allows for flexibility, so I don't hard code the type of engine to use here or the type of AutoOptions to pass. I instead say, I can assign any engine that implements IEngine interface and I can pass any data object that implements the IAutoOptions. So, now you've seen how interfaces work. Let's take a look at an example of using them.
Demo: Using Interfaces
In this first demonstration on interfaces, I'm going to show how we can write an interface and then implement it to drive consistency across multiple engine classes. Earlier in this module I have shown some of these classes, such as engine, accessory, and auto and showed how we can use those to encapsulate our different members, but now what we're going to do is write an interface called IEngine. So let's go ahead and add that. And IEngine is going to have a start and a stop function in it and what that's going to do is guarantee that any class that implements that interface also has start and stop. So let's go ahead and do that by copying up these members, which are both going to return void. So we're going to have a start and a stop, and you'll notice that they don't actually have any code; we end up with a semicolon. Now, if you've used interfaces before with C# or Java or other languages out there, you're already accustomed to this. But if you're new to interfaces, it's important to understand that interfaces are simply contracts. They define things such as different members, whether it fields, or functions, in this case, and what data types they are, what parameters they have, but they don't say what to do; that's up to the class that implements the interface. So, what we're going to do here is we define two what we call stubs, the engine will then implement those stubs. So to do that, we'll (typing) say, "Implements IEngine." Now, by implementing IEngine, I have to guarantee that this class has whatever the interface defines, which is start/stop, obviously, and at this point it should compile and work. So let's go look at what we have, and you'll see that it did work, we have an engine. Now it's important to note that although we can use interfaces in TypeScript, JavaScript does not support the concept of interfaces, of course. Now, if you've been doing JavaScript a long time, you already know that, but if you're newer to it, it's important to take note here that interfaces in TypeScript are only used as you're writing the code, and as you build the code, they're not used at all in runtime. In fact, you will not find any reference in the JavaScript at all to the IEngine interface; it's only going to help us make sure we have consistency as we build our code and ultimately generate the JavaScript. So that's an important distinguishing factor because in C sharp and Java and other languages, interfaces do stick around as the application runs. Not the case with JavaScript. All right, now just to prove this is working as expected and to prove that the build process will take into account this interface, let's go ahead and comment (inaudible) stop, save it. Let's take a look at what we have here, and we get a builder. So it says, "Type engine is missing property stop." Ignore the word property here. It's basically missing the member stop from IEngine in this particular case, the function. And so you can see right off the bat that by not putting this in, we now have a problem. And this is great, especially where you have a lot of code involved, because you can catch your problems up front instead of at runtime. Very, very nice feature when you need it. So, that's an example of how we can implement the IEngine. Now what I can do is make my app even more flexible than it currently is. Right now in the constructor, you can pass in an engine but that means you have to pass an actual instance of the engine. Well let's say that we had another class, (typing), and I'm just going to call this "custom engine" and it implements IEngine. Now let's say that for whatever reason it doesn't make sense for this guy to inherit from engine. So custom engine is not an engine, it's a different type we'll say. But we do want it to have a start and a stop. Now notice right off the bat we get an error here, and it says that we're missing some things, all right; we're driving consistency. So now what I can do is I'll just copy and paste these and what I'll do is when the callback comes in we're going to pass back the startStatus and stopStatus and then the engineType and we'll just put (typing) "custom engine", and we'll put that down here as well, and there we go. So now we've also implemented IEngine on custom engine. So we guarantee that it's going to have a start and a stop. Now, again, if I save it, and if we go over here, let's go find custom engine, you'll see there's no reference again to IEngine. It's only a compile time process, and as you're coding. Now, what we can do, though, is right now this engine field only accepts an engine. Well I also have custom engine now and I might have V8 and V6 and all these others, so if I want to make it more flexible, I can say that you can pass me anything that implements IEngine, and there's one more spot down here, we'll have to fix it, which is a property. You'll see in our get of the engine, we need to now get an IEngine because that's what we're getting out of the field. Now this really ups the flexibility; it makes my code more loosely coupled, because I'm not saying the specific class that you can store in this field, I'm saying that you can store anything that implements IEngine. Very, very flexible now because now we know we can call start and stop on that engine if we want to work with it. All right. So if we were to come down now, we can come in and we can new up an auto (typing). And we're going to have to pass on all of these members here, so we'll pass 40,000. And now for the engine notice the IntelliSense, okay. So I can pass anything that implements IEngine. As a result, I can do a new custom engine if I wanted, which is really nice if I need it. And in custom engine, we already hard code what the type is of the engine, which was custom engine, and then we can do some -- I'll just put, "Make, model, state," and we're ready to go there. And then we can do an alert on auto dot and we can do the engine here. Now let me go ahead and use the one I already have, and you're going to see that we're going to have a problem. Now, what's the problem, because we know engine has horsepower, but now we have two types of engines? Custom engine, if we go back up, notice it only has start and stop. It implements the interface, which only has start and stop, it doesn't have anything else; doesn't have horsepower or engine type. So, we can't get to horsepower because it's storing, although we know it's a custom engine. I can even pass engine here and then we would have to pass, then, the horsepower and the type of the engine. I'll just put "type". It still doesn't work. Why? Well, because the engine, if we mouse over it, is an IEngine and IEngine only supports start and stop. That's it. Now, how can we make it work? Well, if we knew it was an engine we passed in and we do want to call horsepower on it, we can cast it so we can say, myEngine equals auto.engine, but we know that engine is an IEngine, so we can use casting syntax, and we can say we're going to cast IEngine to engine, and now we could say, myEngine.horsePower, and notice it works and we're able to get to the horsepower. Now, the reason we're having to cast it again is because we're being very loosely coupled here, we're saying you can pass me anything that implements IEngine. Well IEngine again only has start and stop that's it. So if we had another type of engine such as this one, that also has horsepower and engine type, we would have to cast that particular field into the engine or the type then we could get to the different members of it. Now again if you've done this with C# or Java this is a very similar concept. But if you're new to this, then that's why we're doing the casting because we have to tell the compiler, "Hey I know I what I'm doing, go from the interface to an engine so that I can get the horsepower and now let's go ahead." And we'll see if we can get an alert here and once this loads up, we should get an alert. There we go 250 horsepower and you can see that it did indeed work. So that's an example of writing an interface, implementing the interface on multiple classes, and then even casting from an interface to a specific type using the TypeScript syntax.
Extending an Interface
Up to this point, you've seen how TypeScript allows classes to inherit functionality from others so that we can extend a base class and make a child class that adds additional features. Well, TypeScript also supports extending interfaces and this makes it easy to define an interface that may be the base and then we can add on additional functionality. So let's take a look at how we can extend interfaces using the TypeScript language. So, here's an example of IAutoOptions interface that was shown previously in this module and it just has a few basic fields that are defined, three fields that must be there and three fields that are optional. Now, if we wanted to take the base set of fields and add additional ones for a different scenario such as a truck, then we can actually use the extends keyword to make a new interface called ITruck options, that extends IAutoOptions. So now what will happen is ITruckOptions, automatically will get all six of these up here and now we're going to add on two additional ones, bed length and four by four with bed length being optional you can see. So, you can see that interface extension is really very similar to class extension; we use the extents keyword, very simple to do. Now it's important to note that with interfaces there is no such thing as an interface JavaScript, this is going to be something that while you're coding up your application it'll help you ensure that your application classes are consistent. So you won't actually see an interface inside of the JavaScript that's generated but it's very good to catch problems up front and also it can be used to ensure consistency as we talked about in the previous section. Now, to actually use that interface ITruckOptions, we can go in to our truck class that extends auto. And you can see that in the constructor here instead of passing an IAutoOptions which only has those six fields, we'll use an ITruckOptions and now we have the eight fields that are supported. And now what I'm going to do is simply pass the data object here the parameter to the super which will be our auto constructor and then we're going to take the bed length and the four by four and assign those up to our different fields. And in this case the bed length is actually a property that will be defined down here in the class somewhere. So, that's an example of how easy it is to extend an interface, let's take a look at how we can use this principle in an application.
Demo: Extending an Interface
In the previous demonstration on interfaces, I showed how we can ride an interface called the IEngine and then implement it across multiple classes to drive consistency and build that code contract into our code, that way as we code, if we forget something we'll actually get in IntelleSense to help us out there and as we compile, if we forgot something that compiler just simply won't generate the JavaScript code. In this demonstration, I'm going to show how we can again define interfaces but also again extend interfaces and we're going to be using these interfaces to write more clean code. Now let me explain what I mean there by clean code, right now if we come down to the auto class, you'll see that we have base price and engine and make model and state and year and all these different parameters. And it gets even worse down in truck because truck adds bed length and four by four. So it now has eight parameters that you must pass. Now, there's nothing wrong with that per say, but as a user of this I have to make sure that I pass the parameters in the proper order and that can get a little bit tricky plus it's just a little messy from a coding stand point. So what we're going to do is we're going to allow an object to be passed into the constructors that implements a specific interface. Now the first one I'm going to do will come back up top here and I'm going to call it IAutoOptions and I have one ready I'm just going to drag in and you'll notice that it has the six members that the constructor currently accepts for auto. So, we have base priced engine, state, make, model and year. Now, if we come back down to auto, you'll see the same exact members here and that's where those members are assigned to the fields or properties. Now, what I'm going to do though is really clean this us though, we're going to say you can pass me in the AutoOptions and this is going to be of type IAutoOptions. So in this particular example, IAutoOptions is not explicitly implemented on any class that I'm going to write. But you're going to see how it's used in a moment. Now, obviously I'm going to have to take the options here and whatever options you pass in will now have these different members. So I'm going to cut and paste this real quick. So now we have one single object that can be passed in which is really going to clean this up for us. Now I could even store if I wanted to get rid of these fields up here, the options object so we could say options, IAutoOptions if I wanted and then completely eliminate these guys and then right here all we'd have to do is say this dot options equals the options but I'm going to go ahead and break out each of these different properties and fields into each individual one because when I new up an auto, in order to get those values if I do it this way, I'd have to say auto.options.engine or state or year or whatever it is. Nothing wrong with that per se but I'm going to leave it as is so that you just say auto.state or auto.engine as an example. Okay, now that's really going to clean it up, but I also need the truck down here to be cleaned up as well and you can see it's really wrong. So I'm going to do the same type of thing but we're going to have a problem. Now, for the super call, the interface has those members and accepts an IAuto option. So we can just past options and that'll take care of fixing that, but now we're missing these two. All right, I can certainly go back up into the interface and add them, but not every auto has a bed length on things. So instead what I'm going to do is define a new interface that's going to extend IAutoOptions. So we'll come in and we'll say interface, we'll call this ITruckOptions and it's going to extend IAutoOptions. Now it's just going to have our two members in it. So we'll have bed length which is a string and we'll have four by four for off road capabilities and that's going to be a boolean. All right. So now what I can do is come down into my truck constructor and instead of passing me an IAutoOptions, I want you to pass me an ITruckOptions. So we'll go ahead and put that in, all right so the ITruckOptions will now have what we need. So now we can simply say options.bedlength and options.FourbyFour and we're ready to go there. So you can see how much cleaner this is. Now it may not be evident why it's cleaner other than there's just one parameter but we'll see that down right here as we actually knew up this truck. So that's our first getting started with extending the interface again I'm not actually using the interface on a class per say explicitly doing it instead I'm doing it behind the scene you'll see in a moment. All right. So if we come back down now what I can do, let's go ahead and get rid of what we had here and comment this back in and I'm going to change this to a truck and then you'll see that we'll get an air. Now here what's really nice about this, I can now pass what looks like in JavaScript terms an object literal and the object literal no allows me to name my parameters. So now I don't have a problem with parameters getting out of order. I can't really simplify the amount of data that's passed because I want all this data to be passed in when you knew off the truck. But I can make it easier to pass the data so you don't things out of order and such and we're doing that here with this object literal. Now, because this guy implements IAutoOptions, it would be fine if this was an auto. So if we change this to auto, the red should go away and we're good to go -- you can see. But if it's a truck the ITruckOptions that we've passed in here has these two extra guests, bed length and four by four. And so you can see we get an air and it's showing us that we're missing some things. So we'll go ahead and fix that and we'll add our bed length and we'll add our four by four all to say it is off road capable, four by four. We're ready to go and you can see it works from there. We can now do an alert on truck dot and we can do for instance, notice is can get right to it or let's just go write out the bed length here. All right, so let's go ahead and run this and there we go, you can see it worked. And now we've really cleaned up our constructor and allowed what is kind of a standard procedure that a lot of things out there follow whether its jQuery plug-ins or others, where instead of passing enormous number of parameters like we had before, we had eight on truck. We now passed one as an object literal. But it just so happens in TypeScript, this object implements the ITruckOptions and then we can get to the options to get to the actual data. Now it's a lot cleaner I think this easier to read because we are very explicit about the parameters that we're passing because we name them. So, that's an example of how we can extend interfaces using the TypeScript language.
Summary
In this module, you've seen how TypeScript provides robust support for code encapsulation; the ability to take members and encapsulate them in a container, which in TypeScript we call a class. Classes allow us to put in properties, fields, constructors, and functions and organize them so that we can get better reuse throughout an application. We've also seen how once you define a class you can extend it. So if we had an auto, as was shown earlier, we can actually derive a truck from it, so we don't have to cut and paste all the auto code into the truck class, we can just inherit it and then extend it, add additional functionality. From there we took a look at interfaces and how they provide a code contract that allows us to ensure consistency across objects. And I mentioned that although interfaces aren't natively supported in JavaScript, and you won't actually see any interfaces in the generated JavaScript code, they're very important at design time or code time as you're writing the application in your editor to catch errors. So if you accidentally forgot to put, for instance, a function that should have been there, by using the interface, the TypeScript compiler will throw an error if you don't satisfy the contract. We also saw how interfaces can extend other interfaces, and we took a look at the IAuto options and how we can extend that to make an ITruck options that builds upon the base interface and adds additional fields or functionality, could even add additional method or function definitions. So that's an example of working with classes and interfaces in the TypeScript language.
Modules
Overview
Modules are an important part of building an application with TypeScript, especially as the application grows 'cause they help you keep you organized. In this module we'll talk about what modules are in relation to TypeScript and JavaScript and we'll go through the different kinds of modules that you can create, internal, external, you can import and export them. And I'll show you how you can manage dependencies using modules and TypeScript. So by the end of this module, you know how to identify a module and TypeScript, the different kinds that you can use, when and where you should use them, places may be perhaps you shouldn't use them, and then the various ways that you can actually implement the modules and code. So we'll take a look at several examples along the way, so let's dive in. ( Pause )
Identifying a Module
Before we start to use modules and TypeScript, it's important to understand what a module is so we can use it properly. So let's start there. Modules help us keep separation in our code. So with JavaScript and with TypeScript, because TypeScript is going to emit the JavaScript, we're going to be able to separate out in different units of work that we have into different modules. We can make them different files, even if we like to. So may we have things that are one module that'll handle data access, and another module might handle UI integration, another one might do animations. By separating the code out, it gives us a lot of great features, things like testability and reusability. And that follows good patterns like separation it concerns and solid. So we want to achieve this modularity with JavaScript and we can do that through TypeScript. Now how do you identify a module? Well, if you see that module keyword, chances are you're going to be a module. Actually, you're always going to be a module if you see the module there. So we explicitly declare that module a keyword and we're creating a module here called dataservice and we could put code inside of there. Another way you get a module is without using the keyword module. You can have implicitly declared one. So on this case, in the bottom, if that's all the code I have in the file, that class and then the variable T, all that code is inside of implicit module. Where does this module get created and what's its name? Well, this module gets created in the global name space or you can call the global module. So in this example here, the test class and the T variable are actually getting created right on top of the global name space. Modules are flexible. We can extend them by creating a module and extending the global name space, or we can create a custom module or decline one, like a data service module and we can keep extending it throughout one file or multiple files. We can also separate these out in a different role. So we can have different modules in the same file or spread across different files, things like a data service module or router module for navigation or maybe an animations module. All these modules, which will I call "Raviolis", these different separated pieces of code are separating our concerns. We can do that in one file or across multiple files. And modules are open. You can import other modules into a module. You can export features from one module to the other and you have full control over what are exposing and making it accessible or inaccessible with the modules. Now let's take a look at a fundamental example of what a module is in TypeScript. ( Pause )
Creating an Internal Module
Let's take a closer look in modules by creating a new module inside of TypeScript file in a project TypeScript modules in module 4 before folder of your solution. If you open up the Scripts folder, you'll see that you have an app and typings folder which are both empty. We're going to fill these in throughout the different demos in this module. So to start off, let's go ahead and right-click on the app folder, choose Add, and then TypeScript File, or you can simply just do New Item, type in TypeScript, let's name this file global-module. On the left we got our TypeScript, the right we have our JavaScript. By default we're just getting the sample of what one could look like. Now when we do this, we're actually already have a module called "Shapes" here. This is an explicitly named module as we created inside of this file. Let's make a few changes here. First, let's actually move and remove the module name. And then let's just de-dent, if that's a word, the class up here and let's get rid of the static member 'cause we're not going to be using it, I want to erase some of the comments, and just kind of trim this down a little bit. And there we go. Now, because we don't have this in the module anymore, I don't need to reference it as Shapes.Point, and I also don't need to export anything. So we haven't talked about what export means yet. What we've done is create an interface. We learned about that previously. We got this IPoint interface. It has one member, getDist, for-- to get the distance. And then we have a class called "Point", which is going to implement the interface. And there's the implementation right here. And then I can create a variable called "p", which is going to be an instance of the point and that can grab the distance from the function that's in here. Now when we're doing this, we still have a module even though we haven't defined a module, everything inside of this file becomes part of a module. And that module is going to extend the global name space or the window objects since we're going to run this in the browser. Let's add a little more code to this, too. So I want to add an alert to the screen. And to do that let's go to Other Windows, going to pull down the Package Manager Console, and we're going to use NuGet. And we're going to pull on a package called toastr. Toastr is going to allow us to write alerts quickly to the windows. So, if you go back to our scripts folder we can see toastr down here and then we also are going to need the typing file for this because we want to use the typings to get the IntelliSense and say that we're using toastr in here. And to use to toastr simply we're going to say, all right, I have a toast and I want to use it as a massage here with info and I want to display the distance. Now notice I'm getting an error here because it doesn't exist in the current scope that's because we haven't pull on the typings file yet. Now, there're two things we could do in this case. One is we could flip over to the definitely type site on GitHub. We could pull down where we have a library of a whole bunch of typings files for different kind of third party libraries or we could just pull it right out of the Before folder. For convenience, let's go ahead and look in your Code folder. And inside of there you should see a toastr-1.2.dts and we'll drag that over to the typings folder. Now, we've got that there. If you look inside of there, you're going to see all these interfaces for a toastr options that we can use inside the file and we're also going to grab the JQuery folder as well. So now we have JQuery and toastr. These are the typings files that we talked about previously. And both of those are going to allow us to then drag toastr into our module. And I can put it anywhere I want. There's some sticking over here on line 9. It's going to snap it up to the top and when I do that, now we get the message of toastr being invalid that goes away. So now it knows what toastr is and if I type dot over here, I'm going to get IntelliSense for info and then we notice we have different overloads for the message. So, toastr is just going to display a little toast in the upper right hand corner for us and it will show us our values. Now, let's take a little step further here and let's put a break point 'cause we can do that inside of our TypeScript file. Now, inside of the app, we've got our TS file over here and we notice we're generating this map file. That's because up in the web essentials under Tools, Options, let me scroll down to Web Essentials which is a great plug-in, you definitely want to use with TypeScript. And down here we can see that we've got our Generate Source Map set to true. That's really, really important. Also, I highly recommend that when you're debugging, to turn this feature off, compile all TypeScript files on build because sometimes it interferes with the map files and getting the right symbols loaded. So once we have that and you see the map file over here, we should be able to set a break point, load it up in Internet Explorer 9 or 10 and then we can run. And notice that the page loads up, we have a start page here and we're running in the first one which is Implicitly Global Namespace. If we click into there, the break point will get hit. So now we can put our cursor over toastr and info and distance because the distance is 5. We can put it over the P there and we get the object for P. We can examine all the values. We can also go into the Locals Window. We can see what's been added to the Global Namespace by us. In this case, we added distance and P and toastr and JQuery, for that matter, into the Global Namespace. Another option is we're going to the command window and we could type in window 'cause that's the base object here. And it's going to show us all the different properties that are inside of the Global Namespace and the ones that we just added in here. Now, let's remove the break point, continue, and let's go back to the browser. And now let's rerun it again and you can see the toast pops up in the right upper right hand corner. So another option that we have is we could run this in a different browser so we could run this down inside of the index html and we go to Browse With. We can open it up in Chrome. And here it is on Chrome. We can go into that same page. Now, it's running up there. Now, I can open the debugging tools here and let's say we flip over to the code under Sources. We can click on global-module.js, and let's set a breakpoint inside of here. Let's set it right down at the toast line. Let's refresh this page. When it hits that breakpoint, notice all the Global variables that we have. These are the Global variables inside of the browser and they're alphabetical, first all the uppercase and then all the lowercase. We should be able to find out point class in here if we scroll up. There it is right there. So, here's our point class. And then we've also got the P and the distance variables that we have. Hard to find with so many things, isn't there? There it is. There's our P and we've also got distance over here. So, all those get added Global Namespace which in general is not a great idea. But if you create a class or variables or functions that are inside of a file and you don't write them inside of a module, that's what you're getting by default. You're getting an internal module that gets added and extended to the Global Namespace. And that's how easy it is to create a module and TypeScript.
Internal Module Accessibility and IIFE
We just took a look at an example of an Internal Module that extends at the Global Namespace. An Internal Module, it can be any local or exported member of another module and that might be a module that's in the Global Module or it can be an external module. So let's explore what some of these means here. When we create a module and we name it, like here with shapes, we're creating an internally named module that we can define and this is going to extend any existing module that maybe named shapes as well. So in this case, we're going to have accessibility for all the values inside of the shapes module, like rectangle in the variable rect and the interface IRectangle. All the accessibility though is this within the module. That means if I define something outside of the module it will not be able to access those. So if I define my rectangle down here and I do Shapes., we're not going to get any IntelliSense with that because the header is going to see, that look, that's inaccessible because nothing internally was exported. So what does exported mean? We can take the same internal module and we can add the export keyword to it and that's going to allow us to then expose or make accessible of the rectangle class outside of the shapes module. So then we can say something like rectangle equals new Shapes.Rectangle and now it's accessible because it was exported. So all we did was add the export keyword to say, "Look, everything inside this module it's accessible within the module. But to make it accessible outside of the module so we can do Shapes., we have to put the export keyword in there." Let's take this step further by extending a module within the same file. Here we have the shapes module, and we're exporting the rectangle class and then we're going to use it. After that, we're going to create another module down below. Actually we're going to extend the same module, modules shapes and we're now, we're going to put a class called Circle in it and export him. So now, outside of the shapes modules we can both use the Rectangle and the Circle class to do what we please. What we're doing is actually extending the Shapes module by using the module keyword and just repeating module Shapes, so you can always open and extend these modules as often as you please. And this makes it really easy to extend these modules. When we create a module on TypeScript it actually emits JavaScript that creates an Immediately-Invoke Function Expression or an IIFE. So what's an IIFE? The IIFE is actually just an Immediately-Invoke Function, exactly as it says. Here we've got a function and at the end of it. Notice the parentheses. So we're defining a function and then we're saying go ahead and run it right now. This means that this doesn't become just a definition of a function, it defines a function and then it runs it right away. This is important because it allows us to wrap functionality and remove things from the global scope. So these outer parentheses will disambiguate the function expression from the statement. That's the difference between the expression from actually running and executing it, going to lock those values in and save that state, so what you're doing is you're minimizing a global scope pollution and any variables or aspects that you create inside of the IIFE are going to be out of the global scope. By creating a module, all those things are only accessible within the module. But when you do that, it's actually emitting JavaScript that actually hides that inside of an IIFE. So how does this look in TypeScript? When we emit an IIFE, on the TypeScript side, we might have something like a module here. And we're exporting a class rectangle so that's going to be accessible outside and we've also got these properties called height and width. So the Rectangle class can have two instance members, height and width. Then we can create a Rectangle by saying Shapes.Rectangle in TypeScript. This will generate an IIFE for us in JavaScript. Now there're two IIFEs in here. The first one we see is the rectangle IIFE. So the rectangle up here is showing us that we can create a Rectangle function, there's the IIFE and executes it, that defines the function for us and it sets to this variable called rectangle. That becomes the constructor for creating a Rectangle. The second IIFE is the Shapes IIFE, that's the module that we're creating it within. So the shapes module then encapsulates the rectangle. Now on the bottom we can just say rectangle equals new Shapes.Rectangle. What we're doing is creating the TypeScript that really makes it a lot easier to type in for us while JavaScript were actually doing is creating this IIFE. So we can write the code in TypeScript which is a little easier to read and that it generates the JavaScript for us using standard conventions like the IIFE which is used in patterns like the module pattern or revealing module pattern, which are common place in JavaScript.
Named Modules
Now, let's create a named module. We're going to the Before solution and inside the Scripts folder. In the app folder, we'll right click and choose Add, TypeScript File, we'll call this in internal-module. First thing we're going to do is get rid of all the code that's in there so we don't have any TypeScript. What we want to do is create a class called Rectangle and I want to put this inside of a module called Shapes. So first, we'll create those modules and classes. Now notice I created an IRectangle interface and I'm telling the class it has to implement. So then I have to define that interface and I can define that up top here to make it accessible to anybody outside of the module or inside of the module. And it is case sensitive. And let's give a rectangle a height and a width and we'll give it a getArea function. Notice we have a problem here with the export because it's telling us it doesn't declare the internal interface, that's because we haven't done that yet. So let's do that now. First we're going to create the constructor for the class and inside of here we're going to accept in the height and width. And by making those public, that's automatically going to create instance members for both the height and the width in the constructor. And then we also have to implement the getArea method. And now we can see this wiggly line goes away. So if I go over here and look at the JavaScript that was emitted, it's all looking good for us and there's out IIFEs. So let's say we didn't implement the getArea, what would have happen there? The error message that we get in TypeScript is actually kind of smart. It tells us that the Rectangle declares the interface but does not implement the whole thing. It's actually missing the getArea method from the type IRectangle. So it doesn't just telling you you're not implementing the interface, it tells you what you're not doing properly. So what have we done? We've created a class that we're exporting outside of this module shapes. So now we should be able to access the shapes by saying something like var rect, create this here, and it should be of type IRectangle, that's the interface that we're expecting. Now let's create a new Shapes.Rectangle. IntelliSense says, yes, you indeed have a rectangle object. And to that we can pass different numbers. I could say 10 by 4. So now we've got our Shapes.Rectangle. If I didn't have this IRectangle in here, for example, let's delete that and move it up inside the module, now notice what happens. I can't define a rectangle that's not in the current scope so I have two options here. One, I can export that interface and keep it within the module and then I could say Shapes.IRectangle and therefore I've got my interface. Or I can keep to where we had it and I can get rid of the export and move the interfaces to the top, put them at the, basically, the global module, and then I can use IRectangle. And that's just the styling choice that you can do. It really depends upon how you want to structure what you're doing inside your module. So now that we have our rectangle, we see and we can access the class rectangle, can we access the getArea method? Let's go ahead and check that out. Let's create an area variable and then let's set the equal to my rect.getArea. We should be able to access that. No problem. And notice that it sees the area is a number. We didn't define that as a number but because it knows through type inference that getArea returns a number. It set it up to be a number for us. Now because we have toastr in the project already as we pulled it in through a NuGet in the previous demo, we can display the area, do the screen like this. Again, we're going to get an error with toastr here 'cause it doesn't know what it is, so we can simply do is go to the typings folder and you'll find toastr-1.2 which we added in the previous demo. If you haven't done that you can find this Dts file, the definition is typings file, anywhere inside of your module Before folder. And now notice we have a reference path at the top. So if we run this in the browser, we can press run up here or we could go down to index HTML and we could choose View in Browser. Now we can click on the second demo Internal Modules - Named, we should see a toast for the area being 40 in the upper right hand corner and that's all simply it does there. Now if we want to debug this we can get out of here and we can come back in and set a breakpoint on toastr. And now we can go in to the Internet Explorer. Now it jumps right into the debugger for us, now if we look at the Locals window you're going to see that we've got in a local, this case, we've got toastr and shapes and rectangle and everything else but we shouldn't have the rectangle class any longer in the Global Namespace. Notice there's no rectangle class there. It's actually inside of shapes. So ideally we'd actually want to move rect and area outside as well and put it in our own module, that way you can remove all of these other variables from the Global Namespace as well. Let's see how to do that. So we can come down here now and say module-- we just called this thing my program for example. And lets go ahead and put the code inside here and we can create a function and that function can just contain the code that we just created and we'll call this function something like run. So now we have our function run right down there. And then at the bottom we could just say go ahead and run it. And now we run this code, let's put a breakpoint there, now we run it. Notice the Global Namespace got a little bit smaller. Actually we're not looking the Global Namespace. We're looking at the name space inside of the myprogram module. So we look inside of this and we scroll down 'till we find window, actually right at the bottom there. There we go. That will show us the Global Namespace. And notice in the Global Namespace I still got Shapes, I got myprograms modules which is one I'm in right now. But I no longer have rect or area inside the Global Namespace. So what we've done is we've effectively move all of our code inside of modules. We got myprogram which becomes its own module, which encapsulates all this code, and we've got the Shapes module. And notice I can actually access the information from the Shapes modules from the myprogram module as we did here by creating the rectangle. This is one way you can create internally named modules. So we've created two internal modules that are named and accessible within the same file.
Extending Modules and Importing Shortcuts
Let's explore the accessibility of an internal module by extending them within the same file and using some shortcuts. So let's go back into the Before solution and inside the app folder, let's create a new TypeScript file. And here, let's call this one extending the internal module. And as a starting point, let's go ahead and delete the TypeScript and go to the Before folder. And let's open this up inside of Notepad and we can copy out and paste all the code that's in there. Now what we're doing is we're creating some interfaces and some modules and it shouldn't compile right out of the gate that's going to help us create some utilities for printing out messages. So if we collapse everything and hit Control M, L to do that, we can see we have an interface for ILogger which has method called write. And then we've got basically in it what's amounts to an enum or just a LoggerMode. We pass in 1 to print to the Console, 2 for the Alert, and 3 to use toastr. And then, inside of this module App.Tools.Utils, we're creating a class called Logger which will actually define the right message for us. This is really important here. We've got a module that's got three dots in it basically. So we've got App.Tools.Utils. You can think of these like Namespace. And then inside of there, we've got our logger which has the write method. And then we have another module down below which implements the Shapes, so it's App.Tools.Shapes. So the top one was App.Tools.Utils, this one is App.Tool.Shapes. So it's a new module extending the first two base one. And this one exposes the point. Then finally we have third module called App.Tools.Shapes which exposes a rectangle. So we've got Shapes which has rectangle and point inside of it. And then we also have App.Tools.Utils which has the Logger inside of it. So, why are we getting an error? Well, because we're actually using inside the logger. We have an option to toastr inside the write method. So if we look inside the constructor, we can see that we've got toastr defined down here and we can simply go over to our typings and drag it into our TypeScript that'll stick the reference right at the top and then it will make all the issues go away and then I can compile it and the JavaScript will be emitted on our right hand side. And you can see define that many modules creates a whole lot of IIFEs and lot of functions in our JavaScript, something that's a lot harder to write that way, but much easier to write inside of TypeScript. So what does this code going to do for us? Let's collapse it all again just for moment. Hitting Control M, L again and let's write some code at the bottom. If I'm going to create instance logger, I need to creat a variable to store it in and I'll say new App.Tools.Shapes. So inside of here I could find Shapes or I could find Utils. And then inside of there, I can say, "All right, well, Utils has a Logger function and I can tell it which logger do I want to use, we'll use toastr." Now that's a whole lot of type there. Notice I've got this big long namespace that I got to type in. Inside of TypeScript, there's a keyword called import that we can use. And I can import into the tools, this can become a shortcut for us, the App.Tools. So now I can simply eliminate the word App down here. It becomes a shortcut to that namespace or to that module. And I could go one set further and create a utilities 1, 2 if I wanted to. So I come down here and I can say create Utils, so then therefore, this guy becomes a lot shorter. Now it's just Utils.Logger. So by doing these imports, looking at the emitted JavaScript, that's actually going to create var statements at the bottom. It's just going to say declare variable called tools and import this namespace. As long as these modules are defined and they're accessible within this file here, we can use them by using the import statement. So that's one way we can create shortcuts. Now let's create an instance of point. So we can say IPoint because that interface is defined at the top, up here, and notice it's in the same accessibility range. So I'll just say create myself a new point. Now notice that the Tool.Shapes.Point works just fine for us, because we're using the shortcut. I can still use a long hand if I'd like to. That works just fine, too. Let's use a shortcut here. And we've got a function called getDist, which will get that value for us and notice it's going to return back a number, because it's looking at the interface for IPoint which exposes getDist as a number. And then finally we can log it out. We can say log.write, 'cause that's the method on the logger. And this is going to use and take advantage of the toastr that we created. So what do we do here? We've got a couple modules, we have App.Tools.Utils and App.Tools.Shapes. So we've got a module for app, module for tools and we got another module for Utils inside of there and one for shape. So we're in emitted JavaScript. If we look inside of the Tools module which is kind of hard to find in some cases, here's our Tools. And now you can see Shapes is defined down there and we're extending the Shapes to include a rectangle, see Shapes.Rectangle. We should also find up here for Shapes to get Tools.Shapes and Shapes for Shapes.Point. So I've extended it through JavaScript by writing it through TypeScript. And this is how we can extend modules and use shortcuts like the import.
Organizing Internal Modules
In the previous samples, we've been showing how to create modules inside of the same file in referencing each other. But you can also do this cross multiple files. So you might want to take your modules, your code for like data access in one module, animations in another, and maybe things like view models or models or anything else you might have, interactions with local storage in different modules. And you can spread them out across your application. This is really ideal for larger apps. When you do this, you have to script them in the right order. So when your refer to the script tags of the JavaScript that's emitted inside your HTML file, you want to make sure that you load them in the proper order based upon their dependencies. This can get difficult to maintain in larger projects, but we're going to take a look at a way to solve that in the upcoming section we can talk about external modules. So how do you refer to an internal module by spreading them out across from files? You simply just use a reference tag. The same way we use the reference with the path to talk to the typings files, the .d.ts files. So how does this work? Let's say that we have a module called Shapes and we put this inside of a file called shapes.ts. The responsibility of the module in that file is to have all the Shapes like rectangles or circles or pyramids. And now we're going to export out the class rectangles so we can use it another modules. So that's all to this file. We might have another file, shapemaker.ts and that's got a module called ShapeMaker. Now he wants to use the Shapes.Rectangle, that's a different module with a different class. Because we've export the rectangle class on top, we can't use that. But to do it, what we have to do is reference that Shapes module first. So we drag the shapes.ts over into the editor for shapemaker.ts, and this creates its reference for us or we can simply type it in. And this allows us to access the Shapes module and its rectangle class that's been exported from the shapes.ts file. So the two keys here, first that we exported the rectangle class and if we had anything else to export, like a function or a variable or an interface, we could also do that from the module inside of shapes.ts. And it's important that if we're going to refer to the interface or any of those things, that we do export them, so that the other modules can use them. The second key is to put the reference down inside the class or the module that's going to use that shapes.ts. So inside of shapemaker.ts we need to have that reference so that it knows, "Hey, I know you don't know what a Shapes is or a Rectangle is, but it's being located in the shapes.ts file." And this will work as long as we load the Shapes.js file before we load the shapemaker.js that's edmitted from these types of files. Let's take a closer look.
Separating Internal Modules
Let's create an example now where we can create several modules, put them in different files so we can create more organized project and show how we reference each other. First, let's go ahead inside the Scripts folder, we have an app folder. We're going to go ahead and add in two modules, we have some starters inside of the code folder in your hard drive. So you look in the Code folder you'll see a shapes and utilits.ts, 04-04, drag both of those into your app folder. Now let's take a look at each one of this. First, let's take a look at the Shapes. Now we look at the Shapes in here. And we can see we've got a module called App.Shapes. We can minimize that. And then down below we're going to import App.Shapes in Shapes. Again, this is just going to reference. Give us a shortcut to the Shapes module which is up here. And then, inside the Shapes module we have an interface for point and rectangle, and then a class for pointing rectangle. And all these are being exported so they can be seen outside of this module which is great because we want to use them right here. So here we can see that we're saying P is of Shapes.Point and then we're going to create a new Shapes.Point right here. Then we can call the methods on it and like where I will do the same thing with the IRectangle when we create a rectangle instance. But now we want to be able to display the values that we got out of the distance in the parameter from these objects. So how can we do that? Well, we have a utilities module over in the Utils.ts file we just pulled in. And if we take a look at him, we can see here he's also inside the module App. So the module App is the root for everything in here. And then inside of the module App we have a module called Utils. We have nested module here and we're exporting the Utils module. So what effect does it we're going to be able to do is say App.Utils for anything inside of the module utilities. Now back inside the Shapes, notice that we had module App.Shapes. The App is use in both places, so if we refer from one to the other they'll both be able to share the same App module extending it. Inside the Utils, we have the interface for logger, ILogger. Where we have this write method, and then we've got a class that we're exporting for logger. And again, this is being exported and so with the interface. So all this is being exported, so anybody who refers to him should have access to the utilities and the method for writing it. So how do we get there? First of all we need to fix the utilities. We've got a problem in here, if we go over and look at utilities we got toastr that's not being used in this scope. It doesn't know what it is. So again, what we can do is go into the typings file, 'cause we have this already in project, drag it over, you pull on the d.ts file. And then now, if we scroll down toastr should be just fine. And the real winner over here is finding out if we press save, do we get compile JavaScript? Yes we do, so we're good to go, now notice it creates an app and then it creates a closure here, basically an IIFE for the app module. And then inside of there you got the utilities module and then you've got the Logger constructor and then so on and so forth. So we've got our code ready to go for the utilities. Now how do we use that inside of Shapes? That's the key. So inside of Shapes, what I really want to do is after I get this distance, I want to able to printout, do I have what the distance is using the utilities. So I want to be able to say, "All right go ahead and this one I've got some variable called log." I want to say log.write 'cause I know that's the method and notice we're getting issues already. So we know we want to say log, we haven't defined that variable yet, so we have to define him. And we know this is going to be a write method, right now it has no idea what this thing is. So up above, what you probably want to do is create an instance of log. Now I after I type in the logger here, we can see that we've got a whole bunch of issues going on. It has no idea what the App.Utils is. It doesn't know what this Utils is, what that Logger mode is. It's just all out of whack. We solve the problem of log.write for now because we've introduce a bunch more problems. But the real issue is we need to know how can we refer to App.Utils inside of the shapes.ts. Well, the quick and easy way to do that is to pull App.Utils, the ts file into the top and it's going to reference it, just like we can reference a .d.ts file we've got the ts out there. Now it knows what this ILogger is. So I now have to find this log as an App.Utils.ILogger and it's going to create a new instance of this logger and pass in toastr. So back we get is some kind of a logger. Now log has a write method in it and notice that it notices the write method right here. We can pass the message in as the string. So everything should be good for that particular method here, and we can make it a little bit cleaner, too. I definitely would like to make a little bit shorter to type. So now we've got an import statement for Utils and I can get read of this app right there. So now we can come down and we can also use the logger down here to say log.write. Now notice we're getting IntelliSense this time, because the last time we did not. So now we can say log.write and put out the perimeter. So we've added in two write statements for our logger. Log is being defined as a new instances utility here. And if we delete all this we can type from the scratch pretty easily just saying here with our new IntelliSense. Let's go ahead and create a new instance of Utils.Logger and notice I'm getting IntelliSense as it pops up. And then I can say App.Logger to get the LoggerMode and then which LoggerMode do I want, I can use Alert, Console or toastr, just use toastr again and then everything is good. So once you pull in that reference that's the first thing you should do, pull the reference in, what it's actually doing is it's merging the app modules from the shapes.ts and then also from the utils.ts. And then this file here, this module in shapes.ts has a Shapes module and then it's going to also now have access to the Utils module. Now the key to this whole thing is when I load these two scripts, I need to make sure that the utilities loads before the shapes. So over in our HTML, if we look in the 4.4 internal access across files, you'll notice that I have two script tags at the bottom of the page. I have to first load the utilities and then the shapes. So if I do this everything should run, let's test this out. And I click on the internal modules across files. And notice I get the parameter and the distance, everything is great. Well let's close this and let's change this up. Let's say that I had Shapes before utilities. That should be a problem. It will still run but what happens when it runs? Now I click on the file again and this time I'm getting issues because I cannot figure out what the logger is, that's because inside the code, if we go back to the Shapes, it has no idea what this logger thing is because it hasn't seen that file yet, Utils has not yet been loaded. The key thing here to remember is that the reference path is really just for the editor. This is showing the editor that, yes, I'm going to tell you what utilities are later. I'm going to make sure I load them in advance at run time. But during design time, just please know that utilities exist and all those types please use the IntelliSense in the type checking so I can make sure that all the code is right. So as you build larger applications you need to make sure that your scripts are appearing in the right sequence. If you have 2, 3, 4 even 10 scripts, it's not so bad. You make sure that you have the third party script first and then you have your other scripts after that in the proper sequence. But once you get beyond that number it gets a little more difficult to maintain and that's where using something like common js or AMD might help, and we'll take a look at that next when we get into external modules.
External Modules and Dependency Resolution
All the examples that we've seen so far in this module about modules has been on internal modules. We've created them. We have defined them and extended them within the same file or multiple files. We reference them from file to file. And we've also seen how to shortcut them if we have multiple dots in our namespaces of the modules. But there's another type of module called external modules and these are really good for helping us with managing large amounts of dependencies in large JavaScript based applications. Some of the traits of internal modules are that they give that namespace like syntax and they're great for grouping common sets of functionality. They're ideal for smaller projects and unlike external modules, there's no need to import an internal module. You just drag the reference over and your off and running. So what do external modules have? The external modules are separately loadable modules, this mean you can load them separate from each other and only as needed. So how do we load an external module? First, we have to have something to export into another module. So if we want to create an external module, we something that's exported from it and then we can simply say import some variable, like viewmodels equals module, the keyword. And then inside the parentheses we pass the name, the string name of the file that contains that module. So in this case it's going to go look for a file called viewmodels.ts in the same path. They can use different paths as well. TypeScript uses CommonJS or AMD Conventions and you can use a library like require.js to employ them. The key thing here, remember, is with external modules, whenever you see the word import, you really want to think external module. So you're going to have some kind of a module that's in a file somewhere and that whole contents of that file is going to become the module and you're going to import it into another variable in some other file. So why even bother with external modules? I mean we've been talking about internal modules up to this point, right? Well, the big thing is, sequencing your scripts and your dependencies and those scripts are really difficult especially in large applications. If you've got lots of files it get be a real pain and a real mess. So how do you deal with that? Well, let's look at an example. So imagine you have some kind of application here like I've got this whole set of scripts inside my app folder and I've got maybe 40 or 50 files, all these are modules. So I have to load this in the right sequence. How do I manage those dependencies in order without something like AMD or CommonJS? That's where the external modules really help you out. So what is this AMD I keep referring to? Well let's define it. It's asynchronous module definition. It helps you load files and modules asynchronously as you need them and you just define upfront which modules depend on which and it will load them in the proper sequence which is a lot easier than having to put all the script files in an HTML file and put them in a proper order yourself. And a load does in sequence based on who is dependent upon who, which is great. And we can use the keyword called requires, so we can say this one requires that one. To use AMD with external modules we're going to need something that's going to help manage these dependencies. Require.js is a great library that does this. If you want to learn more about require.js, you can check on my course Single Page Applications in the module SPA Basics: Separating the Ravioli. I go into detail on how I have a large application there and I use require.js with JavaScript to manage it. So we can use require.js with TypeScript as well. How does this work? Well, let's say we've got an application and in this application we have a file called main.ts, this is the first thing it's going to run on our app. Well we'd have something like a bootstrapper.run. So maybe main.ts is doing a bunch of things and then when it's done getting ready for the application it says, bootstrapper.run where bootstrapper is another module which kicks off the actual loading of the screens perhaps. Well, where is bootstrapper coming from? It's another file so what we can do is with require.js and external modules with TypeScript, we say require and then we tell it there's something called bootstrapper in a file somewhere, it doesn't have to be the same name as the variable. But let's say it was this bootstrapper, maybe.js somewhere and this file is going to be found by require.js and AMD. It's going to have an external module, and then it's going to set that to the variable bootstrapper so then I can run it. Well, before it actually runs it, it's going to go find that bootstrapper file and it's going to check to see what dependencies bootstrapper might have. What we can see in here, there's an important statement right at the top. Where it's saying go get this other module called the greeter. So now I know that I can't run bootstrapper unless greeter has been loaded first. So main depends on bootstrapper and bootstrapper is dependent upon this greeter module. So then it's going to go find the greeter for us and notice there, there are no dependencies in that one, it's just exporting a class called greeter that we can create an instance of. So with AMD and external modules, we can easily create this dependency chain and just tell each module which one that depends upon which and it will load them in a proper sequence. Now let's go check out some examples and show how this can be useful.
Module Dependencies
Let's create a program that uses internal modules and then we'll convert it over to external modules and show some of the benefits that we can get with it. First to start off, let's go with the Before solution and we're going into the Scripts folder, under app, and let's create a new TypeScript file in here. And I'll call this one alerter, so as before 04-05-alerter. We're going to have three different modules in this application, alerter is going to basically send alerts out. It's going to be a service that lets us send messages using toastr based upon when people are coming to our event. And then we'll have another module called dataservice which will give us the data to display in the alert messages. And our final module will be a bootstrapper which will kick everything off. So in the alerter, we're going to create an interface which is going to allow us to show the name of the person and a message. And then we're going to create a class that actually implements its interface. Now we have to implement the members. And the showMessage is going to call into a module called dataservice. And with that module, we want to call getMessage. We're going to have to create this method. It doesn't exist yet. And we're also going to use toastr then to display out a message. So we have two dependencies here, one is on a module dataservice, the other one is on toastr. So how we can handle this? Well, first, we could just comment out these two lines and make sure that our TypeScript will actually compile over to a JavaScript, and it does. Those are our two dependencies there. One thing we can do is for toastr, we can come over and grab it out of the typings. And we'll pull into our file like we learned before. Now this line should be fine. We're good there. Other than it doesn't own messages because we commented this out, so we're going to have to figure out how do we create this dataservice. Well, let's go first and create a dataservice variable. So now we've created these dataservice variables. So it's good down here. But up here, it still has no idea what this thing is. So let's go create that file now. We'll call this 04-05-dataservice. We'll clear out the inside of the file. And the dataservice has a getMessage. So we never going to have an interface here. And we'll also have message that we can use. So now we'll create the class for the DataService. We'll implement that interface. There we go. Notice DataService doesn't have any dependencies at all. We're just creating string and then the message here will get returned once when it calls getMessage. So, how do we deal with this? Well, we can go back now to the alerter and now we can drag in the DataService module. So we go over to the solution, we can grab the DataService pull it in and it creates a reference of the top. And then all of the sudden it's happy. So now when we press Save, we should see all the JavaScripts gets called over here. So now we get the DataService in the alerter, now we need to have something to kick everything off. So we'll create yet another file. And, again, we'll clean out the TypeScript and the bootstrapper is simply going to kick everything off in our application. So we don't need to a whole lot here. We do need to do say alerter.showMessage. I think that was the name of the method. But we know that that does not going to work because I don't have any dependencies in here. So what I need to do now is go grab the alerter, pull it in, and then I need to create an instance of alerter. And now I get my IntelliSense. So I've got my alerter and hopefully that was the name of the method, and it is. So I'm good to go. Now, if we look at this you've got a JavaScript from the right. The alerter works fine. And then we also have our DataService over here. Now one of the things you're seeing already is that when I create these different modules and that these are very small, only couple of lines each and it's easy to tell the dependencies, the bootstrapper requires alerter. So I have to pull that in here then I went to alerter, and alerter requires toastr and the DataService. And I pull the toastr, typings file in. And then I pulled in the DataService one. Now if I run this, we can come down to the index. And again, this is all just using the Internal Modules, the same techniques we've seen. We click on the last one and know we can see "Welcome to the Show!, John." So what happens if we don't put the scripts in the right sequence? We come down to 04-05-external-starter, we can see I have to load jQuery and toastr first. And then I've got to load dataservice, alerter, and bootstrapper. I have to put that in order because the dataservice has no dependencies. The alerter needs the dataservice and toastr. And the bootstrapper needs everybody. So if I take the alerter and the dataservice, very simply just reorder them like this and then try to run that page again, we can view right directly to the page, we're going to see an error dataservice is undefined and we can debug this and find out what's going on. But we know exactly what the problem is here. So instead of having to reorder the scripts and figure this out or drag files in, because remember, when we're doing this dragging in these reference paths, that's just helping out the editor inside Visual Studio. So if we want to make this a lot easier and analyze we can use external modules.
Importing External Modules Using AMD
In the previous demo, we created an application using Internal Modules and we had measure dependencies on their own. Now let's do the same thing but in a new project called TypesScriptAMD which you can find in your Before folder in module 4. We're going to use the same kind of application, but this time we're going to use AMD with it. So inside of the amd-demo folder under scripts you're going to see alerter, bootstrapper, and dataservice.ts file. These are the files that we created exactly as we did in the previous demo. We'll start off here with the alerter and just take a look what we have. Now we're not going to referencing files using the drag and drop reference technique that we use previously. So let's go ahead and let's go through here and get rid of those first. And let's start converting these into AMD modules. The first thing you want to do is make sure that your tools are turned on using TypeScript and you have AMD module set to True. You'll also want to make sure that inside your project file that you have the AMD option set for the TypeScript compiler. And if you look inside of my file here which is also in your Before folder, you'll see I have module AMD set in this file. There's a bug with some of the early versions of TypeScript compiler in the alphas, where I didn't turned this flag on for you. So it's always good to check that and then if you have to save that file and reload your project. So once we do that, we can now start applying the AMD changes to our code. So first, everything inside of this module here, this dataservice.ts file is going to become a module. So think of it as being wrapped inside of something like this, where everything inside of here is actually inside of this module. But we're not going to give it a module. So let's go ahead get rid of all of that. Instead, because it's going to become a module on its own, we have to then tell it, "Look, you want to export this interface and this class." And the reason we have to do this is because this whole thing is a module, if we want to see things outside of the module in other places, in other modules, we need to export these features. Well, this one has no dependencies. So this guy is done. And you'll notice over the right hand side it's turned into this define syntax. So, it's going to define, require, and exports, which means you're going to use RequireJS to handle our AMD syntax. And those are going to define the DataService and the export it. So since were talking about RequireJS let's go into the Package Manager Console for NuGet. Let's install RequireJS. And we'll do that by using Install-Package RequireJS, it will go out to NuGet, hit the servers, and pull down the files that we need into our project. So now we can use RequireJS. Next step is we have to go and do the other two files and covert them over to being modules as well. So let's hit up the alerter next because the alerter uses the DataService. So in the original version of it, we were actually using those references. What we've done is we pulled over a DataService reference like this. We're not going to do that this time because we want to use AMD. So it doesn't know what the DataService is, we have to tell in some other way. So we need to import that module. And we'll do that with an import statement. So we'll say, import and we'll just call it ds, it doesn't matter what we give this variable name. We'll make it say module. So it's going to look and see all right, is there a module called DataService somewhere in this project? There is, this dataservice.ts. It's going to look it up by the name of the file without the ds extension. And it's going to look by default in the same directory that this file is in. I can also go up and down the path change if I type syntax like this. That will go back a folder. Now, it's in the same folder so we want to use that there. Now, if we go here and we say ds., we're going to see syntax for the IntelliSense to show DataService or IDataService, that's because were exporting both of those in the dataservice file. Let's take away the interface for just a moment and come back in the alerter. And we type in here. Now, we can see just dataservice shows up. So this is why we have to export both of these guys inside the file. Next step is we have to make sure we can resolve DataServices, it still doesn't know what thing is, that's just because it's in the module called ds. And then it's the class dataservice, the constructor for creating a new DataService that we have. Is there anything else we need to do? There is actually, because everything in this module is now going to become a module again and these are members in it. Nothing is being exported though. So because we're not exporting anything, well, nobody can use anything in this module. So we want the bootstrapper to kick of the alerter. So we have to say, export the interface and export the constructor class here for alerter. So now, over in the bootstrapper, we still don't know what alerter is but we can import it the same way we did in the other module. So now we can say, "All right, we've got an import of a variable called al." And let's go ahead and get the module called alerter. And as long as there is something called alerter in the project, which there is, that's a module, it will work. And then we can just say al. and notice that it wrapped everything up in that define syntax. Over here is also the define and we've got it here as well. So we've got our three files using the syntax for AMD which is exactly what we want. But now with AMD we have to kick things off with a main or a config file. So let's backup a sec and take a look at the AMD demo HTML file. This was going to kick everything off. In here, we have one script tag, and that script tag has a data-main and it has source. The source is going to point to require.js. That's the library that we pulled down off a NuGet. RequireJS is going to start by looking for this main file. In this case it's going to be scripts/amd-demo/main.js., the JavaScript file. So we're going to have to look for that. We could change this to anything we want like config or papa if we want to. So we're going to have to create this file called main and that's going to be basically its bootstrapper for configuring how RequireJS should look for dependencies. So now we have to create that. Let's go ahead and create a new TypeScript file inside the AMD demo. We'll create, Add, TypeScript and we'll ours main just to match what we had earlier. Now we've got this main file. And simply what we need to do is tell it first where will I find all those scripts? And you do that by saying require.config and then we pass it in object lateral. So here's our object lateral. And the first parameter that object lateral that we want to pass is the baseUrl. And by default, we're going to tell it that we're going to look in the scripts folder, amd-demo. One problem I have is that it doesn't know what this require thing is. So an easy way to solve that is go to the typings file and we're going to drag require to one dts over. Now, I put this in your Before folder automatically but you can always go download the latest version of it, the definitely type of website. And again, this is just going to grab all the types, basically all the interfaces that RequireJS uses. So if you look inside there, you're going to see a bunch of interfaces. Now, the reason we have to pull this one in using the drag and drop technique is because when we run, main JS of course is going to have requireJS running first because the html file refers to in loads RequireJS and it appoints to this main file. So this guy can't even run unless require is there. So now we've configured it to look for all the scripts inside the AMD demo folder, let's tell it, look, when you start up, I want to pass in a string array to tell you which modules I want you to load by default. We want to load the bootstrapper and we could load any others you want, start putting the names in here in the string array. Or we're just going to do the bootstrapper and then we're going to tell-- well, when you come in, what's that parameter going to be called? We'll call that parameter bootstrapper as well. And then we'll use TypeScript to create a function. And that function is simply going to say, okay, go to bootstrapper and call the run method. We can say bootstrapper run and it should go call that module. I've got few syntax errors here. We definitely want to pass the parameters in right order. So this is the first parameter to require, it's the string array list of modules to go load. It's going to find bootstrapper which is right there and then a second parameter is going to be a function, all this at the second parameter. That function is going to accept this as parameters a matching value for the module. So once the module loads, it'll take the value of this variable. And then it will be represented there. So we can say bootstrapper.run, as long as you got a run method inside of here, which we don't. So we want to make sure that we've coded that up as well. So, notice that we have nothing exported in this bootstrapper. Nothing is going to work for us then. So what we probably want to do is create an export for the function called run. So there's a new function we have and we want-- when we run, we wanted to call this code down here. So let's go ahead and put that line up here and this line. And now, because we have said export this function called run, that's going to basically make an accessible outside the module so I can say bootstrapper.run and then it's going to call this code. It wouldn't have work otherwise because these guys were not exposed. So now let's go back to the main. And there's our bootstrapper.run and we can save all these files and the entire project. So we right-click on the amd-demo.html, we can view it in the browser, up pops our message, everything is good. Now if we look inside the developer tools for Chrome and we check out the sources, we can see that all of those files got loaded, dataservice, bootstrapper, and alerter, all got loaded and so the require.js. And that's because inside the HTML file, we loaded that scripts tag which points to require.js, told it to go look for the main JS file. And main JS was this configuration, that's how RequireJS knew what to do. So it went out and found all three files and loaded them in the proper sequence based on dependency order. And all we had to do to our code was add a couple of exports on the interfaces and the classes. We create an export for this function for run and then we imported the modules where we needed them. And the advantage of using AMD with TypeScript and RequireJS is that if you have a large project with maybe 50 or 100 TypeScript files which emit JavaScript, those all going to have dependencies upon each other and it's going to get quite complex. Well, you don't have to figure that yourself. AMD can do that for you if you use this syntax with the imports and the exports.
Importing 3rd Party Libraries Using AMD
If you want to use things like jQuery or other external libraries inside of TypeScript when using AMD, you can do that. Let's take a look at the sample in the TypeScript AMD folder under amd-jquery. And then we can look at the different files, the same ones we had in the AMD demo. Here, let's take a quick look first at dataservice, we didn't changed anything in here, it's just going to get us back this welcome message. Then let's take a look at the alerter. The alerter did change a little. Instead of using the alert message, we're actually using jQuery and then we're also going to use toastr, another third party tool to print out the message. So we're going to put a message on the screen and we're also going to pop it up with the toast. So, how do we do this? Well, those guys don't have modules created in TypeScript, so a couple ways we can do this. One, we could write those modules ourselves and then import them. Or we can just pull in these two libraries right here using the reference and we pull this out of typings and then we can declare the taostr and jQuery using the types that are on those files. JQuery returns jQueryStatic, and toastr returns a toastr. So in those cases, we can just call them, very nice and easy, and we get all of our syntax checking. And it's still going to define the AMD for us. Now because we're not using the import for the module, it's not going to load toastr jQuery when it needs to. There's a couple of ways we could define that. Notice over here, it's just saying that requires dataservice. If we pull those in to the main in advance, we could take care of that. So, one way to do this is to preload jQuery and toastr. What we're doing here in the config is we added the shim. So we're saying shim up jQuery and export to the goal NameSpace, this dollar sign. So we have it accessible. And then, we also have the paths here where we're saying, when I top a jQuery, I want you to go look in the path, that's called jquery-1.8.3, that's the version we're getting, it's going to go down the path and grab the Java Script file. And the same thing for toastr, go grab that version of toastr. So this is going to preload bootstrapper, jQuery and toastr even though we're just using bootstrapper in this case. So now when we run this, we're going to have those three guys load up and then it's going to load off to the bootstrapper, which we can open him. The bootstrapper is going to call the alerter and then the alerter is going to call the dataservice and it's going to use jQuery and toaster. So we right-click on AMD jQuery, you can view it right in the browser and you can see the toast in the upper head corner calling toastr. We can all see jQuery printed this off to the screen for us. And if we look down at the sources, we can see that we had jQuery and toastr are both loaded up with require as well as all the other dependencies that we have.
Modules Recap
Whether you're creating an internal or external modules, they're an important part of TypeScript and understanding them is key to be able to create large scale applications. We have seen that modules can make your TypeScripts more maintainable and make it easier to reuse your code for large scale projects. They're often easy to extend where you can create a module and extend that module later in the same file or in another, you can control your accessibility of variables and functions and other features and elements inside the modules for things that are outside those modules. So you can talk from one module to the other. And you can organize your code across multiple files. And when you look at all these things together, TypeScript modules really make it easier for you to follow good programming practices and standards when creating large scale apps. We look to the two flavors of modules, too, we have internal and external. For the internal modules are really just the developing time references for the tools and type checking. They're the easiest to get going out of the gate with. And to get that reference, you can just drag the file from your solution explorer over into your editor or you can just simply use the triple/reference syntax. But you must sequence your script text properly in an order based upon dependencies when using internal modules because, again, the internal modules are really just getting that static type checking inside the editor. But once you run the code, the emitted JavaScript, those references really don't exist. They only exist in the TypeScript. And that's where external modules can come and help you. External modules will help you do dependency resolution using a tool like RequireJS, it makes much easier. So you can follow the CommonJS or AMD conventions and those external modules will allow you to load a module using the import module syntax where you can load it into another module. So you're going to export one module into another and then reuse them. And whether you chose internal modules or external modules, you're all ready putting yourself on path to create more organized code for your application which ultimately helps you in the long run by creating more maintainable code.
Course authors
John Papa
Dan Wahlin
Course info
LevelBeginner
Rating
(1765)
My rating
Duration4h 25m
Updated25 Mar 2016
Share course