Building a professional API with NodeJS, Typescript, ExpressJS, MongoDB, Jest + Deploy to Heroku — PART 3

Guide:
Part 1: Starting the project and set up a minimal NodeJS REST API
Part 2: Organizing the project, adding routes, controllers and isolated server
Part 3 (you are here): Add typescript support + refactoring all javascript code to typescript and ES6
Part 4: Learn CRUD paradigm and implements it in NodeJS and test with CURL
Briefing
In this article, we will start to add Typescript support into our NodeJS Application and refactoring the previous code.
What you will learn?
In this article, you’ll learn how to add typescript support into NodeJS application and refactoring the previous code with ES6+ syntax and structure project with Typescript.
Let’s get started
Add TypeScript as a dev dependency
yarn add typescript -D
Add @types for Typescript
yarn add @types/node -D
Configure Typescript with tsconfig.json
Inside root directory, in your terminal, run:
tsc --init
This may generate the tsconfig.json file. Let’s edit this config file to include the necessary option to run Typescript:
In tsconfig.json, in compiler options, change the option target from ES5 to ES6.
"target": "es6",
Setup npm script to run the server with typescript + watch file changes
First of all, let’s add the ts-node-dev lib to run in dev mode and watch file changes.
yarn add ts-node-dev -D
In package.json, set up a custom script with these additional options:
- — respawn: default command
- — clear: Will clear screen (terminal) on restart
- — ignore-watch: Files/folders to be ignored by node-dev
- — transpile-only: Consider running this flag which is normal for dev workflow and will speed up things greatly.
In package.json, create the scripts options and add the dev command.
"scripts": {
"dev": "ts-node-dev --respawn --clear --transpile-only --ignore-watch node_modules src/server.js"
},
Now you can run the server. Run from the root folder the command:
// if you use yarn
yarn dev// if you use npm
npm run dev
After start the server, your terminal should seem like this:

At this moment you already have the typescript support, environment, and file watch in your application. That means now you don’t need to restart the server manually anymore. The — watch flag from ts-node will restart the server every time that a file change.
Update javascript files to typescript.
Now that our. project supports typescript, let’s update the files extensions from javascript (.js) to typescript (.ts). Update the file extensions renaming the files of the following files:
- /src/app.js => app.ts
- /src/server.js => server.ts
- /src/routes.js => routes.ts
- /src/controllers/global.js => global.ts
- /src/routes/global.js => global.ts
Now your files should look like this:
Refactoring / Updating the code
Note that your code editor probably warned you about some import/export and syntax issues. This is because now our project expects, in addition to typescript code, a modern syntax, such as import/export instead of require and module.exports. Lets fix it.
Updating app.ts
When using typescript, if the lib doesn’t have built-in types, we need to add them separately. Let’s add the express types:
yarn add @types/express -D
Change from require syntax to import syntax. Your app.ts code should look like this:
import express from 'express'// import our local router file
import routes from './routes'// init express app
const app = express()// allow express to work with json
app.use(express.json())// router
app.use(routes)// export app to import into server.js
export default app
Updating server.ts
Here the only thing we need to change is the require syntax to import. So, your server.ts file should look like this:
import app from './app'
const PORT = 3000
app.listen(PORT, () => console.log("Server is running at PORT 3000 🚀"))
Updating routes.ts
Change the require syntax to import and change from module.exports to export default. Your routes.ts file should look like this:
import globalRoute from './routes/global'
const routes = [globalRoute]
export default routes
Updating /controllers/global.ts
Change the module exports. And probably you code editor warning about req, res params types. For now, as we are not going to worry about the correct typing in this article, add the type any to them. After that, your code should look like this:
const globalControllers = {
healthyCheck(req: any, res: any) { res.send('<h2>API is running</h2>') }
}
export default globalControllers
Updating /routes/global.ts
Change the require syntax to import and change from module.exports to export default. Your routes global.ts file should look like this:
import express from 'express'
import globalController from './../controllers/global'const router = express.Router()// your routes paths and methods
// single basic route at the base path of your application
router.get('/', globalController.healthyCheck)export default router
Update dev script in package.json
The dev command in scripts is trying to run the server.js file instead server.ts. So, let’s fix it. Your dev script should look like this:
"scripts": {
"dev": "ts-node-dev --respawn --clear --transpile-only --ignore-watch node_modules src/server.ts"
},
After that, your terminal should be look like this.

Now we have the server running, structured, supporting typescript and ES6 syntax and with automatic restart with file watch from ts-node-dev.
In the next articles, we will create routes, functionality, CRUDs, connect to MongoDB, create an authentication system and much more. See you in the next article, stay tuned!