Why not JavaScript?

JavaScript is a good option if the project is not too big and don’t end up in a complex ecosystem. Since it is not strongly typed language, possibilities of making mistakes are more compared to a strongly typed languages; but yes it does give more flexibility with the cost of more runtime errors if not done carefully.

What is TypeScript?

This is where TypeScript comes into picture. It is a more solid structured language with optionally static typed variable while having all the features of JavaScript.

How it works?

Typescript is not directly executable by the NodeJS V8 engine, so what we do is, compile it into JS code to be understood by the V8 engine.

Let’s Start

There is a set of dependencies that we have to start with as follows

"express": "^5.0.0-alpha.8",
"ts-node": "^8.6.2",
"tsc-watch": "^1.0.31",
"typescript": "^3.2.2"
  • ts-node is used to compile typescript into JavaScript
  • tsc-watch a watcher typescript compiler to make things easier for auto recompile during a change

There need to be a config file named tsconfig.json in root directory to save the typescript configuration details as follows

{
    "compilerOptions": {
      /* Basic Options */
      "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
      "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
      "lib": [
        "dom",
        "es2017"
      ], 
      "sourceMap": true /* Generates corresponding '.map' file. */,
      // "outFile": "./",                       /* Concatenate and emit output to single file. */
      "outDir": "./dist" /* Redirect output structure to the directory. */,
      "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
  
      /* Strict Type-Checking Options */
      "strict": true /* Enable all strict type-checking options. */,
      "noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
  
      /* Module Resolution Options */
      "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
      // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
      // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
      // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
      // "typeRoots": [],                       /* List of folders to include type definitions from. */
      "types": [
        "reflect-metadata"
      ] /* Type declaration files to be included in compilation. */,,
      /* Experimental Options */
      "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
      "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,
      "resolveJsonModule": true
    }
  }

I outDir, you can define the path for your compiled JS output. At the moment, it is set as ./dist, that is the compiled output will be saved inside directory named dist in your application folder.

Setup Instructions

  1. Create you app directory
  2. Run npm init inside your directory
  3. Run npm i -s express ts-node tsc-watch typescript
  4. Create directory src inside your app directory which should contain all the typescript code including server.ts
  5. Please note that all your code should be in .ts extension

How to Run?

Running is a bit different from the normal NodeJS application as it is running the compiled version other than directly running the ts files.

These are the scripts that I have in my package.json for the project

"start": "npm run build && npm run serve",
"serve": "node dist/server.js",
"start:dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
"build": "tsc"

If you notice the start:dev and serve commands, you can see that we are running the compiled js file which is inside dist directory.

The tsc command will compile the .ts files inside src directory and output into dist directory. These are configured in tsconfig.json (outDir, rootDir).

Attached below is how my final packaage.json looks like

{
    "name": "boilerplate",
    "version": "1.0.0",
    "description": "",
    "main": "dist/server.js",
    "scripts": {
      "start": "npm run build && npm run serve",
      "serve": "node dist/server.js",
      "start:dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
      "build": "tsc"
    },
    "keywords": [
      "node",
      "express"
    ],
    "author": "",
    "license": "ISC",
    "engines": {
      "node": "12.16.1",
      "npm": "6.13.4"
    },
    "dependencies": {
      "express": "^5.0.0-alpha.8",
      "ts-node": "^8.6.2",
      "tsc-watch": "^1.0.31",
      "typescript": "^3.2.2"
    },
    "devDependencies": {
    }
  }

Here is how the project directory structure look like.

So here you have the resources to start a NodeJS project in TypeScript.