This is the first part in a series of tutorials on getting started with TypeScript in a Node.js setting. Part 1 explains the motivation why these tools are used.

Why Node.js?

Node.js has certainly become a powerhouse in the webdev world in the last few years, and for good reasons. It is simple, fast, easy to pick up, and uses JavaScript, which makes many front-end skills transferrable to developing back-end services.

Node.js also comes bundled with npm, a package manager that lets you easily download and use libraries made by other people. npm is the largest repository of open-source software in the world, and libraries exist for any functionality you can think of.

For these reasons (and others I won’t go into), Node.js is a great choice when you are making an API that other applications will connect to, such as providing a back-end service for a mobile app. Node.js also has capabilities for real-time communications through WebSockets, making it very simple to implement real-time functionality for your app, such as chat, games, or any other interactive experience.

Why TypeScript?

JavaScript itself is also simple and easy to pick up, however, because it was originally made for use in a web browser, it has accumulated lots of baggage and issues that can make the unprepared programmer pull their hair out from frustration. One of these major issues is JavaScript’s loose typing, allowing you to dynamically add or remove properties from objects, or mix and match objects of different types without any restrictions. While on one hand this feature gives great flexibility in implementing some feature, it is a major source of bugs which usually are not discovered until the code runs and reaches the affected part. One example is writing obj.propertyname when what you wanted was obj.propertyName, and not finding out about the error until the program has been running for quite some time.

Because you can’t really know if a piece of code works or not until you execute it, programmers have come up with a huge number of testing methodologies and frameworks to ensure that the code they wrote actually does what they think. However, instead of testing out the code by running it, it is possible to run a program that checks the code for the use of missing properties, mismatched types, and proper arguments and return values of functions. This program can warn the programmer ahead of time of errors in their code, which would allow them to fix the errors without actually having to run the code. In essence, it answers the question “Do the components of my program actually fit together?”. This is where TypeScript comes in.

TypeScript is a programming language which is a superset of JavaScript (all valid JavaScript is also valid TypeScript). TypeScript code is compiled into JavaScript, making it possible to mix and match code from the two languages, and to use TypeScript in any setting where JavaScript is used. The main selling point of TypeScript is the addition of type safety to JavaScript, by the use of optional type annotations to variables or properties. These annotations ensure that the variables are used in ways that are consistent and do not lead to issues down the line. Some examples:

In JavaScript, this piece of code would be valid:

var myStr = "foo";
var myNum = 15;
myStr = myNum;    //JS will happily accept this
console.log(myStr.length);    //will output undefined

/* length gives us the number of characters on a string,
but myStr is now a number! This code is valid JS, and
the length of myStr is now undefined. If we were expecting
the length to exist down the line, an undefined length
would potentially lead to major errors. */

Contrast this with TypeScript:

var myStr:string = "foo";   //myStr is of type string
var myNum:number = 15;    //myNum is of type number
myStr = myNum;
console.log(myStr.length);    //will never get here

/* TS will throw a compile-time error at line 3, 
letting the programmer know that it is not possible
to assign a number to a string. */

As we can see from this example, TypeScript will not be allow this code to be compiled and will give the programmer the location of the error. This will allow the programmer to either fix a potential error, or force them to make their meaning unambiguous and clear (for example, if they wanted to assign the string representation of the number 15 to the variable myStr, they must use myNum.toString()). I find this feature greatly useful, since it gives me the piece of mind that my code is properly typed, whereas with plain JS for the most part, I did not even have that. Also, when the time comes to make changes to my classes or interfaces, all my existing code will fail to compile, forcing me to recheck all the uses of my classes and reevaluate the validity of my changes.

What is the cost of using TypeScript?

Of course, we are not talking about monetary cost here, but cost in the sense of what do I have to give up to make TypeScript work for me. For the most part, if you are a JavaScript developer, going to TypeScript is very easy. All valid JavaScript is valid TypeScript, so existing projects can start using TypeScript right away. The syntax of TypeScript matches very well to JavaScript, so the TypeScript learning curve is very low.

However, it is required that you invest some time learning about the tools that enable TypeScript, specifically the compiler. TypeScript cannot be run without being compiled first, and the compiler outputs JavaScript. Setting up the compiler and task-running apps to actually make the compiler usable in your project takes some effort, but once that is done, it can be used throughout the life of the project.

Part 2 will focus on setting up the tools and structure that will enable the creation, maintenance, and expansion of a project all the way to large codebases.