Code in Real-world TypeScript with Node.js, Step by Step

As a great tool for JavaScript, TypeScript is trending. However, it's still new and you may be confused how would one actually use TypeScript in real world?

I've been using TypeScript in my projects since 1.0. In this post, I will create a website in TypeScript, with real-world file structure and technologies.

Though to make this single post more focused on back-end TypeScript, I will not touch how front-end files should be post-processed.

Meet Visual Studio Code

Visual Studio Code is a free, open source, and cross-platform editor that ships with built-in TypeScript support. In this post, I will use Code as the editor. But every thing except the task configuration part can be applied to editors like Sublime Text with latest TypeScript plugin.

Visual Studio Code

Prerequisites

  • Node.js (prefer newer version).
  • tsc (TypeScript compiler) command line tool.
  • tsd (TypeScript declaration) command line tool.

To install tsc and tsd command line tool, open a terminal and execute:

npm install typescript tsd -g

Create and Initialize the Project

To create a project, let's create a folder named code-ts, or whatever you like.

Open this folder in terminal and initialize the project with npm.

npm init

Default values will do.

Now we'll need to install the modules we need for this project:

npm install express vio consolidate handlebars --save

And declaration files for framework/library written in JavaScript:

tsd install express consolidate

tsd comes with a --save option, but I don't recommend using that. The reason is, not all details in declaration files are accurate, and sometimes you may need to make some changes yourself and commit it to your project repo.

The Structure

Here's the file structure we're going to have:

- code-ts
  - static
    - style.css
  - views
    - default.hbs
  - src
    - routes
      - default.ts
    - server.ts
  - bld
    - routes
      - default.js
    - server.js
  - tsconfig.json
  - package.json

tsconfig.json

tsconfig.json tells TypeScript compiler how to compile your code, it also tells the editor how to provide intellisense and error hinting.

A basic tsconfig.json for Node.js could be like this:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs"
    }
}

But the version I'll recommend is like this:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "noEmitOnError": true,
        "noImplicitAny": true,
        "experimentalDecorators": true,
        "sourceMap": true,
        "sourceRoot": "src",
        "outDir": "bld"
    },
    "exclude": [
        "bld",
        "node_modules"
    ]
}

You may want to know more about these options but for now let's just copy and paste.

Build the Web

Open or create following files:

src/server.ts

import * as Path from 'path';

import * as express from 'express';
import { handlebars } from 'consolidate';
import { Router } from 'vio';

let app = express();

app.engine('hbs', handlebars);

app.use('/static', express.static(Path.join(__dirname, '../static')));

let router = new Router(app, {
    routesRoot: Path.join(__dirname, 'routes'),
    viewsRoot: Path.join(__dirname, '../views'),
    viewsExtension: 'hbs'
});

app.listen(1337);

src/routes/default.ts

import { Controller, get } from 'vio';

export default class Default extends Controller {
    @get()
    default() {
        return {
            title: 'Hello, World!',
            content: 'Keep calm and read the source code.'
        };
    }
}

views/default.hbs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
    <link rel="stylesheet" href="/static/style.css">
</head>
<body>
    <h1>{{title}}</h1>
    <p>{{content}}</p>
</body>
</html>

static/style.css

body {
    font-family: sans-serif;
    color: #666;
}

h1 {
    color: #333;
}

Compile The Magic

Now we have all the source code ready, time to compile!

Typically we can run tsc in the directory containing tsconfig.json without specifying an argument. And if we want the compiler to watch the changes of source code and do incremental compilation, we may specify -w or --watch argument:

tsc -w

But let's Ctrl+C and moving back to Visual Studio Code.

Now press Ctrl/Cmd+Shift+B, and you should be seeing a prompt asking you to configure task runner.

Click "Configure Task Runner" and it would create .vscode/tasks.json file with a configuration template.

Let's replace the content with:

{
    "version": "0.1.0",
    "command": "tsc",
    "isShellCommand": true,
    "isWatching": true,
    "showOutput": "silent",
    "args": ["-w"],
    "problemMatcher": "$tsc-watch"
}

And now press Ctrl/Cmd+Shift+B again. If you get lucky, there would be a spinning line at left bottom of Visual Studio Code. Now press Ctrl/Cmd+Shift+U to checkout output of the task.

If everything goes well, you will now have the bld folder with compiled JavaScript files.

And it's time to launch the site:

node bld/server.js

Now you can visit http://localhost:1337/ to see the rendered page.

Try modify src/routes/default.ts and views/default.hbs to see updated outputs.


The router we used in this tutorial https://github.com/vilic/vio.