Build a Light-Weight REST API With Node, Express, and TypeScript
For quite sometime now, Node’s popularity as a JavaScript runtime for developing both frontend and backend applications has really soared. This is — apart from the vibrant community and vast range of packages — mostly due to the modern design concepts baked right into the core of the runtime which has in turn led to the rise of several backend and frontend frameworks.
Welcome to the first part of a three part introductory series into the Express framework. Other articles are:
- Deploy an Express API on a bare metal server
- Build a production ready Node & Express API with Docker
Because you are here, I will assume that you are already sold on the idea of using Node and Express for your backend project. If not, there are tonnes of materials online that outline Node’s key selling points that will convince you, just like they did me — I come from a Python/Django background. While Django is still my go-to backend framework, there are scenarios that justify dropping a “fat, batteries included framework” in favor of a leaner one.
Let’s Dive Right In
Let us start by setting up our project. I am working under the assumption that you have NodeJS and NPM installed on your machine. If not, head over to nodejs.org for some installation instructions. Launch a terminal in your projects directory and:
mkdir express_api && cd express_apinpm init -ynpm i expressmkdir src && touch src/index.js
Let’s add in the usual boilerplate code into src/index.js
:
In my opinion, the above code has become relatively common place it does not require explanation. However, for the benefit of a few:
- We initialized an express app
- Attached a very basic middleware function to it
- Created a dummy endpoint, and
- Defined a way to start the server on the desired port
Let’s update our package.json
file as follows:
We specified src/index.js
as our entry point and added a start
script to run our server. Let’s start the app with:
npm start
And visit http://localhost:3000
in a browser. We should be greeted by our generic Hello From Express
response message. Also, if you check the terminal, there’s a lot of “gibberish” printed out, testament that our middleware function is working.
Wait, What about TypeScript?
Ooh yes!! The JavaScript superset taking the industry by storm. It adds a lot of features to JavaScript notable of which is type-safety. It transpiles down to plain JavaScript and allows us to build scalable and enterprise grade applications with JavaScript.
Still not sold on using TypeScript? Here are a few resources to convince you and get your feet wet with the language:
Let us use TypeScript in our app. Start by installing a TypeScript extension for your IDE. VSCode comes with built-in support so you can skip this step if that’s what you use.
Next, let’s install a couple of libraries:
npm i -D typescript ts-node-dev @types/express
Next, we will tell TypeScript how to transpile our code by using a configuration file. Let’s generate the file using:
tsc --init
This generates a tsconfig.json
file with some reasonable defaults. Let’s update this file as follows:
- Find a setting
rootDir
, uncomment it and update its value to'./src'
- Find a setting
outDir
, uncomment it and update its value to'./dist'
- Find a setting
moduleResolution
and uncomment it. Its default value should be'node'
. If not, set the value to'node'
These are but a few tweaks to get us started. Explanation on what an option does can be found next to it. The TypeScript compiler offers a plethora of options that can be used to tweak its behavior as set in its configuration file.
TypeScript files are denoted by the .ts
extension. We should therefore rename our src/index.js
file to src/index.ts
and update the contents to:
Now this is where the meat and potatoes are:
- We start by importing
express
and the required type definitions for express brought in when we installed@types/express
. Notice theimport
syntax as opposed to therequire
syntax - We then make sure that the value held by the
port
variable is an integer by casting whatever value is received from environment variables or the provided default - We then specify the types for the parameters in our middleware function. If we do not, TypeScript complains that they are implicitly of type
any
- We then initialize our app stating that it is of type
express.Application
. This will help catch errors should we call a method or property that is not specified in the type definition - Notice on line 13 how we do not specify types for
req
andres
. However, if you were to hover over them, TypeScript will tell you the inferred types. If you attempt to set them to different types, TypeScript will complain effectively preventing you from introducing bugs into the code. This is a feature we do not get with JavaScript
Let’s once more update our package.json
, this time with some handy scripts:
npm run dev
starts up our development server usingts-node-dev
. This has all the usual niceties including “watch-mode” which automatically reloads the server should the code changenpm run build
transpiles our TypeScript code and creates corresponding files in the specifiedoutDir
. Adist
folder ‘magically’ appears when run and in there isindex.js
which is the ES5 version of our TypeScript codenpm start
uses the transpiled code to start our server. And just in case you forgot to build the code, theprestart
hook makes sure the code is transpiled
And now, for the moment we’ve all been waiting for, let’s use npm start
to start our server one last time and visit http://localhost:3000
in a browser. We should be greeted by the generic response Hello From Express With TypeScript
.
Congratulations, you have built your first Express app with TypeScript! The code is available at:
Summary
In this article, we just but scratched the surface of what is possible with Express and TypeScript. One can go ahead to set up linting with typescript-eslint , create a CRUD API employing a database and an ORM/ODM or implement advanced concepts such as setting up the Express app in true object oriented fashion.
Worthy of note, is an NPM library that can be used to generate an Express app with TypeScript for those starting from scratch.
As with any generated code, it is important to understand how it works and edit to suit your use case.
Fastify is an interesting NodeJS backend framework that is gaining traction. It’s been touted to be faster than Express as it introduces less framework overhead. It has TypeScript support and an interesting plugin system. Check it out here:
Happy coding and see you in the next article!