TypeScript Tutorial - An Introductory 9 Part Guide
JavaScript's universal browser support and dynamically typed nature makes it an ideal universal web language. However, as any developer who comes from an object-oriented background knows, JavaScript's flexibility can become a liability as applications grow larger and larger. That's why Microsoft created TypeScript to help developers produce better JavaScript utilizing the principles of object-oriented programming.
In this article, we're going to go over what exactly TypeScript is as well as show you how to get started in using it.
What is TypeScript?
TypeScript is what's called a superset of JavaScript. It's not a replacement for JavaScript, nor does it add any new features to JavaScript code. Instead, TypeScript allows programmers to use object-oriented constructs in their code, which is then translated to JavaScript. It also includes handy features like type safety and compile-time type checking. Best of all, it's completely free and open source.
TypeScript 2.3 is the latest version of the language as of mid-2017. If you're already familiar with the superset but have been out of the loop, TypeScript 2.0 introduced some major improvements including more comprehensive error-catching and the ability to obtain declaration files directly via npm install.
Although TypeScript was developed by Microsoft and comes standard with Visual Studio (an IDE software), it can be used in any environment. New and veteran coders alike can benefit from utilizing the superset. This TypeScript tutorial will give you the tools you need to start churning out better JavaScript for your web projects.
The benefits of TypeScript
The are various benefits to using TypeScript, a few of these include:
- Thanks to static typing, TypeScript code is more predictable and easier to debug than JavaScript.
- Object-oriented features like modules and namespaces make organizing large code bases more manageable.
- The compilation step catches errors before they reach runtime.
- The popular framework Angular is written in TypeScript. Although you can also use regular JavaScript with Angular, most tutorials you'll find for the framework are written in TypeScript. Anyone who wants to take full advantage of Angular and similar development platform will be better off knowing TypeScript.
- TypeScript is similar to CoffeeScript, another language that compiles to JavaScript, but the former is more flexible than the latter thanks to static typing.
Part 1 - Installation and set up
Visual Studio 2017 already comes equipped with the TypeScript plugin, and it is included in update 3 for Visual Studio 2015. If you're using an older version of Visual Studio or a different environment, you can get the TypeScript source code and install it as a Node.js package:
npm install -g typescript
Once installed, you can start making TypeScript files and adding them to existing applications. TypeScript files can be identified by the *.ts
extension. Whenever you save a TypeScript file, the Visual Studio plugin automatically generates a corresponding JavaScript file with the same name that's ready for use. Every time you create a new TypeScript project, you'll notice that an app.ts
file containing the default code implementation is also generated.
Visual Studio offers a wonderful side-by-side view for corresponding TypeScript and JavaScript files. Whenever you save your TypeScript, you can immediately see the changes in your JavaScript.
This is similar to if you're using codepen.io. With CodePen, you can write your TypeScript code and then view the compiled JavaScript. Below is a side-by-side comparison of some uncompiled TypeScript and compiled JavaScript code in CodePen.
The examples in this TypeScript tutorial will assume that you're using Visual Studio, but several other IDEs and text editors also offer TypeScript support including auto-complete suggestions, error catching and built-in compilers. WebStorm, Vim, Atom, Emacs and Sublime Text all have either built-in support or plugins for TypeScript.
Part 2 - Compiling to JavaScript
Since .ts
files cannot be directly used in browsers, they must be compiled to regular JavaScript, which can be accomplished in a few ways. Aside from using an IDE or an automated task runner like Gulp, the simplest way is to use the command line tool tsc
as follows:
tsc index.ts
The above command will give you a file named index.js
. If a .js
file with that name already exists, it will be overwritten.
It's also possible to compile more than one file at once by simply listing them:
tsc index.ts main.ts
You can compile all of the .ts
files in the current folder with the following command, but keep in mind that it doesn't work recursively:
tsc *.ts
To automatically compile whenever changes are made to a file, you can set up a watcher process:
tsc index.ts --watch
If you're working on a large project with many .ts
files, it may be helpful to create a
a tsconfig.json
file. You can read more about configuration files in the TypeScript docs.
Part 3 - Static typing
The defining feature of TypeScript that separates it from JavaScript and CoffeeScript is static typing support, which allows you to declare variable types. The compiler makes sure that variables are assigned the correct types of values, and it can even make inferences if type declarations are omitted.
In addition to several primitive types like "number," "boolean" and "string," you can also use a dynamic type called "any." "Any" is similar to the "dynamic" keyword in C# in that it allows you to assign any type of value to the variable. For this reason, TypeScript doesn't flag type errors for "any" variables.
Variables are declared in TypeScript the same way they are in JavaScript. You can declare a type by adding a colon and the type name:
var num: number = 45;
In the above example, the variable num has been assigned the type "number." You can read about all of the available data types in the TypeScript documents.
Part 4 - Arrays
With TypeScript, you can create arrays using brackets as such:
var array: string[] = ['dog', 'cat'];
var first: string = array[0];
The above TypeScript would give you the following JavaScript:
var array = ['dog', 'cat'];
var first = array[0];
As you can see, arrays in TypeScript are accessed with a zero-based index. You can also build complex variables using primitive types:
var name = { firstName: 'Steve', lastName: 'Jobs' };
Even if you don't explicitly assign a type to the variable as in the above example, TypeScript infers that "name" is a complex object with string variables. If you were to later assign anything other than a string to any of these variables, you would get a design-time error.
Part 5 - Interfaces
Defining an interface allows you to type-check combinations of variables to make sure they go together. Interfaces do not translate to JavaScript; their sole purpose is to help developers. For example, you can define an interface with its properties and types as follows:
interface Food {
name: string;
calories: number;
}
You can then tell a function to expect an object that fits your "Food" interface to ensure that the right properties will always be available:
function speak(food: Food): void {
console.log("This " + food.name + " contains " + food.calories + " calories.");
}
Now, when you define an object that has all of the properties your "Food" interface expects, types will automatically be inferred. If TypeScript suspects you've made a mistake, the compiler will let you know. For example, take the following code:
var cherry_pie = {
name: "cherry pie",
caloreis: 500
}
In the above example, one of our properties is misspelled, so you should expect an error message like this:
main.ts(16,7): error TS2345: Argument of type '{ name: string; caloreis: number; }'
is not assignable to parameter of type 'Food'.
Property 'calories' is missing in type '{ name: string; caloreis: number; }'.
Property order doesn't matter so long as the required properties are present and of the correct type; if that's not the case, you'll receive a warning from the compiler like the one above.
Part 6 - Classes
Classes in TypeScript work mostly the same as classes in other object-oriented languages. Since the ECMAScript 2015 update was released, classes are also now native to JavaScript, but the rules for classes are a little stricter in TypeScript.
You can create a simple TypeScript class as follows:
class Menu {
items: Array<string>
pages: number;
}
Properties are public by default, but they can be made private. Once you establish some classes, you can then set up constructors to simplify creating new objects.
Instead of giving each class its own file, you can also combine short classes that go together, such as Point, Size, and Rectangle, into one file. Try to keep such combined classes under 150 lines of code to avoid any problems.
Part 7 - Generics
When working with variables of different types, it may be helpful to set up a generic. Generics are reusable templates that allow single functions to accept arguments of different types. This technique is preferable to overusing "any" type variables since generics preserve types.
Take a look at the following script, which receives an argument and returns an array containing that same argument. The "T" following the function name indicates a generic. When the function is called, all instances of "T" will be replaced by the provided types:
function genericFunc<T>(argument: T): T[] {
var arrayOfT: T[] = [];
arrayOfT.push(argument);
return arrayOfT;
}
var arrayFromString = genericFunc<string>("beep");
console.log(arrayFromString[0]);
console.log(typeof arrayFromString[0])
var arrayFromNumber = genericFunc(45);
console.log(arrayFromNumber[0]);
console.log(typeof arrayFromNumber[0])
In the above example, the type is manually set to string when we first called the function. This step isn't required because the compiler knows which argument has been passed and can infer which type is appropriate the next time the function is called.
Even though it's not a necessity, it's good to get into the habit of always providing the type in case the compiler makes a mistake, which is something that can happen as your code becomes more complex. Combining generics with interfaces practically guarantees that the resulting JavaScript will be flawless.
Part 8 - Modules and namespaces
Modules provide yet another way to organize and consolidate code. If used effectively, splitting your code into reusable components can cut down on your project's number of files thus making maintenance much easier. In TypeScript, internal modules are referred to as "namespaces" while external modules are just called modules.
TypeScript has a special syntax for exporting and importing modules; however, the language can't directly handle the wiring between files, so we need some third party libraries to facilitate the use of external modules. Specifically, we use RequireJS for browser apps.
Imagine you're working on a browser app, and you have two .ts files: one for exporting a function; and another for importing and calling the function. They would look as follows:
exporter.ts
var sayHi = function(): void {
console.log("Hello!");
}
export = sayHi;
importer.ts
import sayHi = require('./exporter');
sayHi();
Now, to implement your module, you first need to download require.js and tack it on to a script tag. Then, you must set an extra parameter to let TypeScript know that you're using require.js, which is done as follows:
tsc --module amd *.ts
Learning how to use modules in TypeScript takes time, yet the payoff is immense. You can read more about them in the TypeScript docs on modules.
Part 9 - Third party declaration files
When you need to use a library originally intended for regular JavaScript, you must apply a declaration file to make it TypeScript compatible. Declaration files, which have the extension .d.ts
, hold information about libraries and their APIs. You could make your own declaration files by hand, yet you can just as easily find a .d.ts
file for any library you need already created by someone else.
The best place to look is DefinitelyTyped, a massive public repository with literally thousands of libraries. While you're there, you can also pick up Typings, a handy Node.js module for managing your TypeScript definitions.
Summary
Using TypeScript is almost always preferable to directly writing JavaScript. Even if you're completely comfortable with JavaScript, taking some time to learn TypeScript will make you a faster and more efficient web developer. TypeScript however, isn't the only "alternative" JavaScript language there is. Other popular choices include CoffeeScript (as previously mentioned), Babel, and Elm.
As can be seen by the Google Trends graph above, the other choices are fairly popular as well. However, TypeScript seems to be rising in popularity, making it a great reason to learn more about it.