worl.co

I’m , a software developer and writer living in New York.

Building an API Backend with TypeScript and Express - Part One: Setup

TypeScript gives JavaScript developers a much-needed type-safe option for front-end development, but it works just as well in a Node environment. Node even includes many next-generation JavaScript features that older browsers don’t ship, so you won’t need any post-processing tools like Babel or Webpack/Browserify. In this tutorial I will assume you have a basic understanding of the command line and have a recent version of Node and NPM installed. I would also recommend using Visual Studio Code because it has good out-of-the-box support for TypeScript.

We’re going to build a basic backend API with Node and TypeScript. We’ll use the popular Express web framework for the basic building blocks. In future posts, we’ll expand into database persistence, code organization, advanced TypeScript features, and more. In this post, we’ll just cover getting our TypeScript environment set up and creating a “Hello World!” route with Express.

If you don’t already have TypeScript installed, you can install it with npm install -g typescript in a terminal. At the time of writing, the current stable version is 2.1.

Now we can get started! cd into wherever you’d like to store this project, and run mkdir ts-express; cd ts-express. Then run npm init to create the package.json file describing the application. You can leave the defaults as they are.

You now have all the of the basic scaffolding to get started with TypeScript. It works very similarly to any other Node project, and your general workflow will be the same as a regular JavaScript project. We can now install our dependencies from NPM.

npm install --save express body-parser

Because these are JavaScript libraries, we need TypeScript definition files to get the full benefit of type-checking when we use them. These definition files declare the module layout and exported types for each library. You can install the definitions for Express and the body-parser middleware like this:

npm install --save @types/express @types/body-parser

Now let’s write some TypeScript! Open up your editor of choice into the ts-express directory and start by creating a src directory. This directory will hold our TypeScript code. Later we’ll configure where the TypeScript compiler should output our code. Once you’ve created the src directory, create a new file called app.ts. We’re going to place all our code in this file to start with and learn more about code organization later.

As a base, we’ll start with a simple JavaScript version and slowly convert it to TypeScript. All valid JavaScript is valid TypeScript. If you have a legacy JavaScript project to convert, you can start by changing all the file extensions from js to ts and incrementally adding types until you’re satisfied. Any compiler errors about types when compiling this un-typed code are really more like warnings: the TypeScript compiler just keeps going.

// src/app.ts

var express = require('express');
var app = express();

app.get('/', function(req, res) {
  res.send('Hello World!');
});

app.listen(3000, function() {
  console.log('Example app listening on port 3000!');
});

This code starts an Express server, adds one root route, then starts listening on port 3000. That’s about as stripped-down as you can get. Now let’s compile it!

$ tsc src/app.ts

Obviously compiling all our files one at a time as we write more code is not pleasant, and we definitely don’t want our compiled JavaScript sitting next to our TypeScript files. The TypeScript compiler has a configuration file to let us fix that.

Here’s the tsconfig.json file I’m going to use for the remainder of this project. Put it in the root of the project.

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": false,
    "removeComments": true,
    "preserveConstEnums": true,
    "outDir": "build",
    "strictNullChecks": true,
    "sourceMap": true,
    "target": "es2015"
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "**/*.spec.ts"
  ]
}

I’ve highlighted the important options. outDir tells the compiler to output our compiled code into a directory named build. Don’t worry about creating it, the compiler will do that for us. strictNullChecks forces us to be correct about knowing if any of our variables can be null, which will save you some annoying debug time later when something is unexpectedly null or undefined. target tells the compiler to compile our code into ES2015 JavaScript syntax. Other options include ES3 and ES5, which you would most likely use when targeting browsers because of their more limited feature set. In general, TypeScript tries to support as many previous versions as are reasonable and possible for their advanced features like async/await.

Now you can compile with tsc and, hopefully, not receive any errors. Your code will output into the build directory as specified in tsconfig.json. You can now run the code:

$ tsc
$ node build/app.js
Example app listening on port 3000!

That’s all for this section! The next section will explore TypeScript’s type-checking, defining different routes, and validation.

Now check out Part Two - Routing and Validation.