Photo by Steve Harvey on Unsplash

Prerequisites

For this tutorial, you need to have these tools installed:

Node.js come with NPM who can install Node.js modules, so feel free to use it. I'm more comfortable with Yarn.

About Typescript

TypeScript is a free and open-source programming language developed by Microsoft that aims to improve and secure JavaScript code production. This is a superset of JavaScript (that is, any correct JavaScript can be used with TypeScript). TypeScript code is transpiled in JavaScript and can be interpreted by any web browser or JavaScript engine. The first version was released in 2012.

Typescript brings more comfort in the writing of the syntax. It’s a good choice to use it because :

  • An optional static type of variables and functions
  • Object-oriented programming support
  • Module import
  • It supports the ECMAScript 6 specification.
  • The ability to compile down to a version of JavaScript that runs on all browsers
  • IDE provides IntelliSense to make you write the code more faster
  • Helps you implementing SOLID principles into a language that doesn’t really support it.
  • The code is easier to test

Initialize node project

Create a folder, then go inside

mkdir node-typescript-starter
cd node-typescript-starter

Since we are inside the folder, we will initialize a Node.js project by running the command yarn init then you will have to answer some questions. Here is the output you will have:

node-ts-starter-yarn-init
Initialize a Node.js project

A file named package.json will be created, and it is the configuration file for a Node.js project.

Add typescript

yarn add typescript
yarn add -D @types/node

The first line installs Typescript in the project, and the second line installs the definitions of the types for modules that come with Node.js like http, fs, path, cluster, etc...
Note that the CLI option -D the second command indicates that we want to install this package only for development, so it will not be installed if we are in production mode.
Now we need to set up the configuration for Typescript. It consists of a file where we define rules that Typescript will use to check and build our code. For example, Which version of Javascript we are targetting, directories to exclude or include in type checking, enable or disable some type check rule, and so on.

yarn tsc --init
# or
npx tsconfig.json

These two commands have the same goal but produce a different result.

  • The first command generates a tsconfig.json file with comments on each property, which helps understand the purpose of this last. I will recommend this command to someone who just starting with Typescript.
  • The second command generates a tsconfig.json file with many predefined properties already configured, contrary to the first who have few properties. I recommend this for someone who already uses Typescript for a long time.

You can customize the tsconfig.json as you want. I will provide the one I use on all my projects in the project repository at the end.

Write code

Now it's time to write some code. Let's create a folder then create a file inside. Feel free to use your preferred editor or IDE.

mkdir src
cd src
touch index.ts

Open index.ts and paste write the code below and save:

const addition = (a: number, b: number): number => {
    return a + b;
};

const number1: number = 5;
const number2: number = 10;
const result: number = addition(number1, number2);

console.log('The result is %d', result);

Execute the project

We wrote our super function, which calculates the sum of two numbers, and we want to execute it. I will tackle this in 3 steps to show you all possibilities.

Compile the file, then run with node

The Node.js runtime runs javascript code only, and since our is in Typescript, we have to translate it to javascript then run it. We achieve this by running the command below:

# Inside the folder node-typescript-starter
yarn tsc
node build/index.js

The output will be similar to the picture below:

node-ts-starter-compile-and-run

Run the Typescript file directly

Now we can execute our code, but it's required to run to command to see the result. Why can we just execute our .ts file directly? Also, we only need Javascript files at the moment we want to deploy in production. Hopefully, it's possible through a Typescript runner called ts-node. We will first install it then run our project with:

# We only need it for development
yarn add -D ts-node 

Now the package is installed so every time we need to run our code, we just need to this:

yarn ts-node src/index.ts

Execute the file on change

Now we can run our file with one command instead of two but, I find it hard to run this command every time I have made a change in my files. Is there a way to run files on change? (Yess, I'm a lazy developer 😛).
Hopefully, there is a package called nodemon which can do this for us, so let install it then see our to use it.

yarn add -D nodemon

Before you start editing your files, you just need to run this command:

nodemon --watch "*.ts" --exec "ts-node" ./src/index.ts

This command means: Watch every change on all files with the extension .ts, then use ts-node to run them by using the located at ./src/index.ts as the entry point
Note: If you want to add another file to watch, for example, a .json file, add another CLI option --watch follow by ".json."

nodemon --watch "*.ts"  --watch "*.json" --exec "ts-node" ./src/index.ts

Configure ESLint and Prettier

ESLint helps us write a better code by checking if our code is well written, well-formatted, and respects some rules defined as the best practices for maintainable and consistent code.
Let install the necessary dependencies.

yarn add -D eslint eslint-config-prettier eslint-plugin-prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser

Create a file .eslintrc.js at the root folder of the project and add this code:

module.exports = {
  parser: '@typescript-eslint/parser',
  extends: ['plugin:@typescript-eslint/recommended', 'prettier/@typescript-eslint', 'plugin:prettier/recommended'],
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
  },
  env: {
    es6: true,
    node: true,
  },
  rules: {
    'no-var': 'error',
    semi: 'error',
    indent: ['error', 2, { SwitchCase: 1 }],
    'no-multi-spaces': 'error',
    'space-in-parens': 'error',
    'no-multiple-empty-lines': 'error',
    'prefer-const': 'error',
  },
};

The important part of the code below is the rules property. It is here we define our rule. For example:
semi: 'error' means a semicolon is required at the end of an instruction.
prefer-const means the use of let is forbidden and use const instead.
You can find available rules here, and feel free to customize as you want.
If a rule is not respected, the line will be underlined with a red or orange line depending on if you set the error level for this specific rule to error or warning respectively.

Create a file .prettierc at the root folder and add the code below:

module.exports =  {
  semi: true,
  trailingComma: 'all',
  singleQuote: true,
  printWidth: 150,
  tabWidth: 2,
};

In this file, we define rules that prettier will use to format our code for us.
semi: true means prettier would add a semicolon at the end of a line if we forgot to do that.
tabWidth: 2 means prettier will indent lines with two spaces.

Add a script in our package.json to fix all ESLint errors:

...
"scripts": {
  "eslint:fix": "eslint --fix",
 }
...

Now run yarn eslint:fix to see the command in action

Bonus: Type Inference

Typescript has a great feature that consists of guessing the variable type based on the value assigned to the last one or guess the return type of a function based on the value returned. Let do some example:

const isValid: boolean = true; // type is explicit
let age: = 44; // Typescript will give the type of value `5` to the variable `age` who is a Number
const word = "5"; // Typescript will do the same so `word` is a type String
number = word; // Typescript will show and error because a String can't be assigned to a number.

We can now refactor our code to remove unnecessary types. The advantage of doing that is the fact that our code will more readable avoid boilerplate code.

const addition = (a: number, b: number) => { // Typescript will guess the function returns a number
    return a + b;
};

const number1 = 5;
const number2 = 10;
const result = addition(number1, number2); // Result will be a number

console.log('The result is %d', result);

Now we have a good starter to build an awesome Node.js application using Typescript. You can found the project at this link.

Reach me on Twitter for any questions. See you at the next one.