[Archived] Getting started with Typescript on the backend with Node.js and Express
Omkar Kulkarni / February 08, 2022
7 min read • ––– views
Caution
This article is over 2 years old. There's far better tooling available now, so it's better if you use that.
There are lot of guides on the internet about setting up Typescript with Node.js -Express server. They miss out on a lot of stuff such as hot reloading, compilation, and deployment.
We will also dive deep into explanation of small but important options. This would serve as (pun-intended :P) a one stop guide to setup Node.JS-Express API server with Typescript!
So let's get started 😎
Setting up our project
I will be using VS Code for this project setup which is fairly common and really intuitive IDE. Run the following command to create a new folder
bashmkdir node-express-ts
and then cd
into it
bashcd node-express-ts
Creating package.json
Now we will need to generate a package.json
file which will be required to install our dependencies, manage our start scripts, etc
bashnpm init
Now simply enter the relevant info in the terminal. Note that we are not particularly interested in repository section of package.json so feel free to press enter when it asks about it
json{
"name": "node-express-ts",
"version": "1.0.0",
"description": "Express, Node.js with TypeScript Starter",
"main": "dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "your name",
"license": "MIT"
}
Installing TypeScript 📦
Let us go ahead and install Typescript in our project. You will need to run the following command to install Typescript.
bashyarn add typescript
Setting up tsconfig.json
📜
It is fine if you don't have typescript installed globally. Typically what it allows us to do is, the ability to run tsc
command from terminal.
It is recommended that you generate a tsconfig.json
via tsc command. It provides some good out of the box defaults.
Run the following command to generate a nice tsconfig.json
file for us
bashnpx tsc --init
You should see something like this in the terminal
bashmessage TS6071: Successfully created a tsconfig.json file.
Open tsconfig.js
. You would see a lot of options. Don't worry about it as most of them are sensible defaults so you can leave them as it is. What we are particularly interested in is, outDir
outDir
is the directory where our compiled Javascript code will reside. It is the code that is expelled out bytsc
compiler command.
So let's modify it to the following setting
json"outDir" : "dist"
json{
"compilerOptions": {
"outDir": "dist",
"incremental": true,
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": [
"node_modules",
"**/*.test.ts",
"./node_modules",
"./node_modules/*"
]
}
More dependencies
We would build our server on top of Express which is a lightweight and minimalistic web framework for Node.JS
Let's run this command to get our dependencies installed
bashyarn add express cross-env cors dotenv helmet rimraf
cross-env
- Takes care of setting/injecting environment variables so we don't have to care about the platform we run our code oncors
- Ah yes the cors. I actually recommend you try and deploy both frontend and backend on the same domain so you don't have to deal with this monster of a error. But still I am including it for the sake of completeness. This package essentially enables cors on the server and allows incoming requests from domains we whitelist.dotenv
- Environment variables injector for Node.js. It picks up environment vars from .env file and injects intoprocess.env
of Node.jshelmet
- As the name suggests, it adds some secure headers on your app.rimraf
- Enables us to delete dist folder between deploys so we can delete old code before new one is compiled. (It runsrm -rf
behind the scenes)
Installing Typescript types for packages
A lot of these packages are included with type definition files but some of them require them to be downloaded from a community managed repo, DefinitelyTyped
Run the following command to install project dependencies
bashyarn add -D @types/node @types/express
One final thing!
We would need nodemon
to watch for changes and essentially hot reload our server.
Let's install nodemon
bashyarn add -D nodemon
Commands configuration
There are couple of commands involved with this setup. The final scripts would look like the following and I will explain what each script does.
json"scripts": {
"build": "rimraf dist && tsc",
"dev": "nodemon src/index.ts",
"start": "cross-env NODE_ENV=production node dist/src/index.js",
"prestart" : "npm run build",
"typecheck": "tsc --noEmit"
}
- build - This command deletes the old dist compiled code.
- dev - Script that hot reloads our server upon changes
- start - Runs our server in production environment
- prestart - This script is automatically picked up by npm and ran before
start
command. - typecheck - I always run this before committing on github. You don't want to break CI due to a type-error.
If you have made this far, have a cookie. (Like seriously have one :P) 🍪
Creating files
Create a src
folder in the project with index.ts
file.
Add a console.log('Hello from index.ts');
to check if everything is wired correctly.
save the file and run yarn dev
if you see
bashHello from index.ts
mission success!! 🏆 Now let's go ahead and do the sweet express setup.
Express setup.
Add the following code to index.ts
tsimport express, { Express, Request, Response } from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import helmet from 'helmet';
// make sure to create an .env file in the root of the project!
dotenv.config();
const app: Express = express();
const port = process.env.PORT || 5000;
app.use(helmet());
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/', async (req: Request, res: Response) => {
res.send(`
<h1>Welcome to Node Express TS API Server! </h1>
<p>
NODE_ENV: ${process.env.NODE_ENV}
PORT: ${port}
</p>
`);
});
app.listen(port, () => {
console.log(`Node.JS-Express API 📀 listening at http://localhost:${port}`);
});
Here we have setup express to use helmet, cors, json() and urlencoded() middleware.
We also setup a index route that essentially renders some HTML with NODE_ENV and PORT so we don't have to check terminal for it.
Deployment
Go ahead and push this code on Github. Make sure to put .env
and node_modules
in .gitignore
Now all you have to do is run npm start
on your hosting service. It will build our app and serve it on the configured PORT. I use Railway but you can use popular service like Heroku to run Node.js API
If you encountered any error during setup, please make sure
- You installed all the dependencies correctly
- Typescript is at the latest version
- Delete the
dist
folder and try again
Verdict
We saw how to setup node.js API with Typescript from scratch till deployment. I think Typescript is an amazing language and it does make a lot sense to use it on the server because of less context switching.
Further improvements
- You can add cookie-parser middleware that enables express server to read/parse and send cookies.
Hope you enjoyed this tutorial! Follow me on Twitter and visit my Portfolio to know more about me. Read my previous blog about an amazing GraphQL Schema builder!
Happy coding 😎