This tutorial teaches how you can build, structure, test and debug a Node.jsNode.js is an asynchronous event-driven JavaScript runtime and is the most effective when building scalable network applications. Node.js is free of locks, so there's no chance to dead-lock any process. application written in TypeScript. To do so, we use an example project which you can access anytime later.
Managing large-scale JavaScript projects can be challenging, as you need to guarantee that the pieces fit together. You can use unit tests, types (which JavaScript does not really have), or the two in combination to solve this issue.
This is where TypeScript comes into the picture. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
In this article you will learn:
- what TypeScript is,
- what are the benefits of using Typescript,
- how you can set up a project to start developing using it:
- how to add linters,
- how to write tests,
- how to debug applications written in TypeScript
This article won’t go into to details of using the TypeScript language itself, it focuses on how you can build Node.js applications using it. If you are looking for an in-depth TypeScript tutorial, I recommend checking out the TypeScript Gitbook.
The benefits of using TypeScript
As we already discussed, TypeScript is a superset of Javascript. It gives you the following benefits:
- optional static typing, with emphasis on optional (it makes porting JavaScript application to TypeScript easy),
- as a developer, you can start using ECMAScript features that are not supported by the current V8 engine by using build targets,
- use of interfaces,
- great tooling with instruments like IntelliSense.
Getting started with TypeScript & Node
TypeScript is a static type checker for JavaScript. This means that it will check for issues in your codebase using the information available on different types. Example: a String
will have a toLowerCase()
method, but not a parseInt()
method. Of course, the type system of TypeScript can be extended with your own type definitions.
As TypeScript is a superset of JavaScript, you can start using it by literally just renaming your .js
files to .ts
, so you can introduce TypeScript gradually to your teams.
Note: TypeScript won’t do anything in runtime, it works only during compilation time. You will run pure JavaScript files.
To get started with TypeScript, grab it from npmnpm is a software registry that serves over 1.3 million packages. npm is used by open source developers from all around the world to share and borrow code, as well as many businesses. There are three components to npm: the website the Command Line Interface (CLI) the registry Use the website to discover and download packages, create user profiles, and...:
$ npm install -g typescript
Let’s write our first TypeScript file! It will simply greet the person it gets as a parameter:
// greeter.ts
function greeter(person: string) {
return `Hello ${person}!`
}
const name = 'Node Hero'
console.log(greeter(name))
One thing you could already notice is the string
type annotation which tells the TypeScript compiler that the greeter
function is expecting a string
as its parameter.
Let’s try to compile it!
tsc greeter.ts
First, let’s take a look at the compiled output! Ss you can see, there was no major change, only that the type annotations were removed:
function greeter(person) {
return "Hello " + person + "!";
}
var userName = 'Node Hero';
console.log(greeter(userName));
What would happen if you’d change the userName
to a Number
? As you could guess, you will get a compilation error:
greeter.ts(10,21): error TS2345: Argument of type '3' is not assignable to parameter of type 'string'.
Tutorial: Building a Node.js app with TypeScript
1. Set up your development environment
To build applications using TypeScript, make sure you have Node.js installed on your system. This article will use Node.js 8.
We recommend installing Node.js using nvm, the Node.js version manager. With this utility application, you can have multiple Node.js versions installed on your system, and switching between them is only a command away.
# install nvm
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
# install node 8
nvm install 8
# to make node 8 the default
nvm alias default 8
Once you have Node.js 8 installed, you should create a directory where your project will live. After that, create your package.json
file using:
npm init
2. Create the project structure
When using TypeScript, it is recommended to put all your files under an src
folder.
At the end of this tutorial, we will end up with the following project structure:
Let’s start by adding the App.ts
file – this will be the file where your web server logic will be implemented, using express.
In this file, we are creating a class called App
, which will encapsulate our web server. It has a private method called mountRoutes
, which mounts the routes served by the server. The express instance is reachable through the public express
property.
import * as express from 'express'
class App {
public express
constructor () {
this.express = express()
this.mountRoutes()
}
private mountRoutes (): void {
const router = express.Router()
router.get('/', (req, res) => {
res.json({
message: 'Hello World!'
})
})
this.express.use('/', router)
}
}
export default new App().express
We are also creating an index.ts
file, so the web server can be fired up:
import app from './App'
const port = process.env.PORT || 3000
app.listen(port, (err) => {
if (err) {
return console.log(err)
}
return console.log(`server is listening on ${port}`)
})
With this – at least in theory – we have a functioning server. To actually make it work, we have to compile our TypeScript code to JavaScript.
For more information on how to structure your project, read our Node.js project structuring article.
3. Configuring TypeScript
You can pass options to the TypeScript compiler by either by using the CLI, or a special file called tsconfig.json
. As we would like to use the same settings for different tasks, we will go with the tsconfig.json
file.
By using this configuration file, we are telling TypeScript things like the build target (can be ES5, ES6, and ES7 at the time of this writing), what module system to expect, where to put the build JavaScript files, or whether it should create source-maps as well.
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "dist",
"sourceMap": true
},
"files": [
"./node_modules/@types/mocha/index.d.ts",
"./node_modules/@types/node/index.d.ts"
],
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
Once you added this TypeScript configuration file, you can build your application using the tsc
command.
If you do not want to install TypeScript globally, just add it to the dependency of your project, and create an npm script for it:
"tsc": "tsc"
.
This will work, as npm scripts will look for the binary in the ./node_modules/.bin
folder, and add it to the PATH when running scripts. Then you can access tsc
using npm run tsc
. Then, you can pass options to tsc
using this syntax: npm run tsc -- --all
(this will list all the available options for TypeScript).
Are you looking for help with enterprise-grade Node.js Development?
4. Add ESLint
As with most projects, you want to have linters to check for style issues in your code. TypeScript is no exception.
To use ESLint with TypeScript, you have to add an extra package, a parser, so ESLint can understand Typescript as well: typescript-eslint-parser
. Once you installed it, you have to set it as the parser for ESLint:
# .eslintrc.yaml
---
extends: airbnb-base
env:
node: true
mocha: true
es6: true
parser: typescript-eslint-parser
parserOptions:
sourceType: module
ecmaFeatures:
modules: true
Once you run eslint src --ext ts
, you will get the same errors and warnings for your TypeScript files that you are used to:
5. Testing your application
Testing your TypeScript-based applications is essentially the same as you would do it with any other Node.js applications.
The only gotcha is that you have to compile your application before actually running the tests on them. Achieving it is very straightforward, you can simply do it with: tsc && mocha dist/**/*.spec.js
.
For more on testing, check out our Node.js testing tutorial.
6. Build a Docker image
Once you have your application ready, most probably you want to deploy it as a Docker image. The only extra steps you need to take are:
- build the application (compile from TypeScript to JavaScript),
- start the Node.js application from the built source.
FROM risingstack/alpine:3.4-v6.9.4-4.2.0
ENV PORT 3001
EXPOSE 3001
COPY package.json package.json
RUN npm install
COPY . .
RUN npm run build
CMD ["node", "dist/"]
7. Debug using source-maps
As we enabled generating source-maps, we can use them to find bugs in our application. To start looking for issues, start your Node.js process the following way:
node --inspect dist/
This will output something like the following:
To start debugging, open the following URL in Chrome:
chrome-devtools://devtools/remote/serve_file/@60cd6e859b9f557d2312f5bf532f6aec5f284980/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9229/23cd0c34-3281-49d9-81c8-8bc3e0bc353a
server is listening on 3000
To actually start the debugging process, open up your Google Chrome browser and browse to chrome://inspect
. A remote target should already be there, just click inspect. This will bring up the Chrome DevTools.
Here, you will instantly see the original source, and you can start putting breakpoints, watchers on the TypeScript source code.
The source-map support only works with Node.js 8 and higher.
The Complete Node.js TypeScript Tutorial
You can find the complete Node.js TypeScript starter application on GitHub.
Let us know in the issues, or here in the comments what would you change!