Why do I prefer TypeScript and is ordinary JavaScript not enough?

Before we start

Summing up

Wondering what is better for your application – TypeScript or JavaScript? This post is not about that. It is worth noticing that every valid JavaScript code is also a valid TypeScript code, so it does not take you anything. If you want to, you can stop using types and write play js code.

Nearly a month ago, the new version of TypeScript (2.5.2) was released.  It introduced some new features, which reminded me of how beautiful Typescript is. That’s why I decided to describe how simple it is to write a web app with Express.js and TypeScript and why do I prefer to use them.

Why do I prefer TypeScript and is ordinary JavaScript not enough?

You can find many arguments on why TypeScript is better than JavaScript or vice versa. However, this post is not about them. It is worth noticing that types in TypeScript are optional. Every valid JavaScript code is also a valid TypeScript code, so it does not take you anything. If you want to, you can stop using types and write play js code.

Why do I use Express.js, when there are other newer frameworks?

Express.js has some really powerful features which other frameworks do not have.
Definitely, it is the most mature Node framework that includes:

  • more contributors
  • more updates
  • fewer issues
  • more problems solved

Express.js is really lightweight. I used many popular web frameworks like spring or spring bot in java, asp .NET in c# or laravel in PHP. They are great but too fat. They ship with too many dependencies.


Before we start

The main question is: what kind of application will we build? We will create a simple web application using mentioned tech stack. It is worth to show, how easily with the use of Express.js we can develop properly secured app from scratch. You can do it without tons of dependencies and external libraries, where you have to trust the author’s code.
They also can be poorly written.
I assume that you have installed npm with Node, Mysql and your favourite code editor. I chose Visual Studio Code.
Let’s install the following dependencies.
At first, Express.js with Sequelize ORM and Mysql driver.
 npm i -S express sequelize mysql2 
As I said before,  express.js is lightweight and plugin-oriented, which means that we need to install some plugins/middleware to handle everything beyond basic functionality.
npm i -S body-parser cookie-parser cors express-validator
We want to include user’s authentication into our app, so we need libraries for handling jwt tokens and password hashing.
npm i -S jsonwebtoken bcrypt
Finally, we need TypeScript with types.
npm i -D typescript @types/bcrypt @types/body-parser @types/cookie-parser @types/cors @types/es6-promise @types/express @types/express-validator @types/jsonwebtoken @types/node @types/sequelize
It is essential to mention npx. Notice that everything above was installed locally. For some reasons, it is better to install libraries in that way, but those installed globally are easier to run. Npx allows you to use packages installed locally as they are installed globally.
npm i -g npx
I’ve organised my folders in the following structure.
Backend with Node: Express.js, TypeScript, Sequelize
Generally, you only need tsconfig.json and index.ts files from here (for now), but it is nice to organise your folder correctly.

Our TypeScript config file specifies:

  • which files need to be compiled by ts,
  • where to put the compiled file,
  • module system,
  • Javascript ‘version’
  • source maps for easy debugging in the future

App entry point: index.ts

Fill index.ts like above, run start npx tsc --watch with node dist/index.js and type in your browser localhost:4001 and here it is. Comment lines define middlewares which are optional for now, but we need to enable cors and parsing json from post body, so better uncomment this.
Now, we have to connect with the database using Sequentlize.

Next, we should define the database with the required tables. For our app, the only table with users is mandatory.

I will create two similar routes in this app. First one is going to be unprotected. Access to the second route will be granted based on the jwt token. We need to define a database user model.

I’ve created four different user models. The last one is the most important. It allows us to query the database using Sequelize. Others are just types and names are self-descriptive.

Prepare and secure routing

Our app will contain four routes:

  • /register
  • /login
  • /some-resource
  • /some-protected-resource

We need to create an appropriate router and service for them. We also need to define post body validator, which will be checking user credentials for example.
Here we have user service that contains methods for:

  • signing in,
  • signing up
  • verifying jwt token

I do not want to expose the entire user model in the response body. In the code below you can see only id and email.

Our token guard middleware will check the existence of token in protected requests. If the token is not provided, it will return 403.

In the next step, we define rules of post body data validator for the appropriate route. Notice that you can specify them in your way. I prefer to expose as a plain js object.

Let’s define route logic and apply validator to the corresponding route.

Notice that the order of registering middleware is essential. Firstly, we define the unprotected route, then we register token guard middleware. It will be applied to any routes defined below.

Summing up

It wasn’t so hard or time-consuming to write own authentication/authorisation middleware. It is an independent, easily extensible, and we developed it, so we know how it works. We don’t need to worry about magic code or unexpected behaviour while the app grows.
Thank you for your attention. If you have any questions, please leave a comment.


Other worthy reads