We're live-coding on Twitch! Join us!

Node, a run-time environment that makes it possible to write server-side JavaScript, has gained a lot of adoption since its release in 2011. Writing server-side JavaScript is incredible but can get messy as the codebase grows, owing to the nature of the JavaScript language; dynamic and weak typed.

Developers coming to JavaScript from other languages often complain about its lack of strong static typing; this is where TypeScript comes into the picture, to bridge this gap.

TypeScript is a typed (optional) super-set of JavaScript that can make it easier to build and manage large-scale JavaScript projects. It can be thought of as JavaScript with additional features such as strong static typing, compilation and object oriented programming etc.

Note: TypeScript being a super-set of JavaScript means that all JavaScript code is valid TypeScript code.

Here are some benefits of using TypeScript:

  1. Optional static typing.
  2. Type inference.
  3. Ability to use Interfaces.

This tutorial will primarily teach you to set up a Node project with TypeScript. We will build a simple Express application using TypeScript and transpile it down to neat, reliable JavaScript code.

Let’s begin!

Prerequisites

  1. This tutorial assumes a basic knowledge of Node

Setting up

In this section, we will go over the setup and configuration required to enable our computer to run a simple Node application using TypeScript.

Installing Node

This step is only necessary if you do not already have Node installed on your machine. If you do feel free to skip.

Let’s begin by installing the Node run-time on our machine. If you are on a Debian or Ubuntu distro of Linux, fire up a new instance of the terminal and run the following commands:

$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
$ sudo apt-get install -y nodejs

You will need curl installed on your machine to run the first command. Curl is a command-line tool for transferring data using various protocols.

If you are on a different operating system, head over here for Node installation instructions.

Once the installation is complete, we can confirm that it was successful by checking the Node and Npm versions installed:

$ node -v
$ npm -v

At the time of writing this article, the stable versions for Node and Npm are 10.15.1 and 6.7.0 respectively.

Initializing an Npm project

Now that we have Node and Npm installed, we will create a new folder for our project and initialize it as an Npm project:

$ mkdir node_project
$ cd node_project
$ npm init

Note: After running npm init, you will need to supply Npm with information about your project. However, if you'd rather let Npm guess sensible defaults then you can add the y flag: npm init -y

Installing Dependencies

We have successfully initialized a bare Npm project but haven’t installed the dependencies required to runTypescript. Navigate into the project directory we just created and run the following commands on the terminal:

$ npm install -D typescript
$ npm install -D tslint

The -D flag is the shortcut for: --save-dev. You can learn more about this here.

Wonderful, now we need to install the Express framework:

$ npm install express -S
$ npm install @types/express -D

The second command above installs the Express types. We need this package because TypeScript and Express are independent packages hence there is no way for TypeScript to know about the types of Express classes.

Types in TypeScript are files, normally with an extension of .d.ts*, used to provide type information about an API, in our case Express.

Configuring TypeScript

In this section, we will setup TypeScript and configure linting for TypeScript. TypeScript uses the tsconfig.json file to configure the compiler options for a project. Create a tsconfig.json file in the root of the project directory and paste in the following snippet:

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist"
  },
  "lib": ["es2015"]
}

Let’s go over some of the keys in the JSON snippet above and see what they do:

  • module : Specifies the module code generation method. Node uses commonjs.
  • target: Specifies the output language level.
  • moduleResolution: This helps the compiler figure out what an import refers to. The Valuenode mimics the Node module resolution mechanism.
  • outDir: This is the location to output .js files after transpilation. We save it as dist.

ProTip: An alternative to manually creating and populating the tsconfig.json file is running: tsc --init. This command will generate a nicely commented tsconfig.json file. To learn more about the key value options available, check out the official TypeScript documentation.

Let’s now configure TypeScript linting for the project. In a terminal that is pointed to the root of our project’s directory, run the following command to generate a tslint.json file:

$ ./node_modules/.bin/tslint --init

Open the newly generated tslint.json file and add the no-console rule accordingly:

{
  "defaultSeverity": "error",
  "extends": ["tslint:recommended"],
  "jsRules": {},
  "rules": {
    "no-console": false
  },
  "rulesDirectory": []
}

By default, the Typescript linter prevents the use of our favorite debugger, console, hence the need to explicitly tell the linter to revoke its default no-console rule.

Updating the Package.json file

At this point in the tutorial, we can either directly run functions in the terminal or create an 'npm script' to neatly run them for us. Let’s go with the latter, we will make a “start” script that compiles and transpiles the TypeScript code, then runs the resulting .js application.

Open the package.json file and update it accordingly:

{
  "name": "node-with-ts",
  "version": "1.0.0",
  "description": "",
  "main": "dist/app.js",
  "scripts": {
    "start": "tsc && node dist/app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/express": "^4.16.1",
    "tslint": "^5.12.1",
    "typescript": "^3.3.3"
  },
  "dependencies": {
    "express": "^4.16.4"
  }
}

In the snippet above, we updated the main path and added the start command to the 'npm scripts.' Taking a close look at the start command, we are first running the tsc command and then the node command. This will enable us to compile and run the generated output with node.

NOTE: The tsc command tells TypeScript to compile the application and place the generated .js output in the specified outDir directory as it is set in the tsconfig.json file.

Setting Up The Folder Structure

We will create a src folder in the root of our project directory and then create a file called app.ts within it:

$ mkdir src
$ cd src
$ touch app.ts

At this point, we should have a folder structure that looks like this:

├── node_modules/
├── src/
  ├── app.ts
├── package-lock.json
├── package.json
├── tsconfig.json
├── tslint.json

Creating and Running a Basic Express Server

Now that we’ve configured TypeScript and its linter, we will build a basic Node Express Server. Open up the app.ts file and paste in the following code snippet:

import express from 'express';

const app = express();
const port = 3000;
app.get('/', (req, res) => {
  res.send('The sedulous hyena ate the antelope!');
});
app.listen(port, err => {
  if (err) {
    return console.error(err);
  }
  return console.log(`server is listening on ${port}`);
});

The code above describes a basic Node Server which simply listens on the port 3000 for requests. Let’s run the app using the following command:

$ npm start

If it runs successfully, we get a message logged to the terminal “server is listening on 3000.” Now we can visit_ _http://localhost:3000 on the browser and we will see this message “The sedulous hyena ate the antelope!

We can now open the dist/app.js file and we will find the transpiled version of the TypeScript code:

"use strict";

var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const app = express_1.default();
const port = 3000;
app.get('/', (req, res) => {
    res.send('The sedulous hyena ate the antelope!');
});
app.listen(port, err => {
    if (err) {
        return console.error(err);
    }
    return console.log(`server is listening on ${port}`);
});

//# sourceMappingURL=app.js.map

Awesome, you have successsfully set up your Node project to use TypeScript!

Conclusion

In this tutorial, we went over a few reasons that make TypeScript important to writing reliable JavaScript code. We also looked at some benefits of working with TypeScript.

Finally, we followed simple steps and learnt how to set up a Node project with TypeScript.

Like this article? Follow @JordanIrabor on Twitter