Creating a TypeScript Express.js Web Application with ES6 - Step-by-Step Guide

Last Updated:

1: Create A New Directory for your application

Create a new directory for our Express server.

mkdir express-api

Change your directory so that you are inside the newly created folder

cd express-api

Initialize your package.json file.

pnpm init

2: Add The Project Dependencies

Install the Express Framework

pnpm i express

Install Typescript

pnpm i -D typescript @types/express @types/node

Initialize your tsconfig.json file.

pnpm tsc --init

Inside of the newly created tsconfig.json file, declare your outDir.

-  // "outDir": "./",       /* Specify an output folder
+  "outDir": "./dist",      /* Specify an output folder

3: Write your Express Server:

Create a new src folder.

mkdir src

Create your app.ts file. This is where your server code will live.

touch src/app.ts

Add your server code:

express-api/src/app.ts
import express from 'express';
 
const PORT = 5000;
 
const app = express();
 
app.get('/api', (req, res) => {
  res.send('Server Running...');
});
 
app.listen(PORT, () => {
  console.log(`Server listening at http://localhost:${PORT}/api...`);
});
 
export default app;

4: Run Your New Express Server

Compile your typscript code. The compiled code will be saved in the ./dist directory from step 2 above.

pnpm tsc

Run the compiled server code

node ./dist/app.js

5: Add an Endpoint with Return Data

Let's create a new route so that we can serve up some data. Since our data object is made up of different members of The Beatles, we will call our route /api/beatles

app.get('/api/beatles', (req, res) => {
  const data = {
    title: 'The Beatles',
    beatles: [
      {
        'first name': 'John',
        'last name': 'Lennon',
        instrument: 'Guitar',
      },
      {
        'first name': 'Paul',
        'last name': 'McCartney',
        instrument: 'Bass Guitar',
      },
    ],
  };
 
  res.json(data);
});

The fully updated file will look like this:

express-api/app.ts
import express from 'express';
 
const PORT = 5000;
 
const app = express();
 
app.get('/api', (req, res) => {
  res.send('Server Running...');
});
 
app.get('/api/beatles', (req, res) => {
  const data = {
    title: 'The Beatles',
    beatles: [
      {
        'first name': 'John',
        'last name': 'Lennon',
        instrument: 'Guitar',
      },
      {
        'first name': 'Paul',
        'last name': 'McCartney',
        instrument: 'Bass Guitar',
      }
    ],
  };
 
  res.json(data);
});
 
app.listen(PORT, () => {
  console.log(`Server listening at http://localhost:${PORT}/api...`);
});
 
export default app;
 

Let's repeat step 4 above by running:

pnpm tsc
node ./dist/app.js

Now, if you go to http://localhost:5000/api/beatles, you will see that our Beatles data is being served for us!

Next, let's see what happens if we add one more Beatle to our data object. Without stopping the server let's go ahead and make the following update:

express-api/app.ts
import express from 'express';
 
const PORT = 5000;
 
const app = express();
 
app.get('/api', (req, res) => {
  res.send('Server Running...');
});
 
app.get('/api/beatles', (req, res) => {
  const data = {
    title: 'The Beatles',
    beatles: [
      {
        'first name': 'John',
        'last name': 'Lennon',
        instrument: 'Guitar',
      },
      {
        'first name': 'Paul',
        'last name': 'McCartney',
        instrument: 'Bass Guitar',
      }
    ],
  };
 
  res.json(data);
});
 
app.listen(PORT, () => {
  console.log(`Server listening at http://localhost:${PORT}/api...`);
});
 
export default app;

But wait... If you look back to http://localhost:5000/api/beatles, our beatles data didn't change, we don't have our third Beatle!

6: Add Hot Reloading:

We can fix this by adding some additional npm packages to help us watch our code for changes.

Go ahead and stop your server by hitting ctrl-c or ctrl-d on your keyboard.

Add nodemon and ts-node

pnpm i -D nodemon ts-node

Next, open up your package.json and add the following start script. We are going to just delete the test script, but you can leave it if you prefer:

express-api/package.json
"scripts": {
  "start": "nodemon --watch 'src/**' --ext 'ts,json' --exec 'ts-node src/app.ts'"
},

Let's go ahead and run our server once more.

pnpm start

You will see the following in your terminal:

➜  express-api pnpm start
 
> express-api@1.0.0 start  /your/directory/path/your-project-name
> nodemon --watch 'src/**' --ext 'ts,json' --exec 'ts-node src/app.ts'
 
[nodemon] 3.0.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**
[nodemon] watching extensions: ts,json
[nodemon] starting `ts-node src/app.ts`
Server listening at http://localhost:5000/api...

Now, if you go back to http://localhost:5000/api/beatles, you will see all three of our Beatles.

To make sure that our server code is actually hot-reloading, let's add one more Beatle to our data object.

Go ahead and add

{
  'first name': 'Stag',
  'last name': 'Beetle',
  instrument: 'Mandible Harp',
}

Your updated server code should now look like this:

express-api/src/app.ts
import express from 'express';
 
const PORT = 5000;
 
const app = express();
 
app.get('/api', (req, res) => {
  res.send('Server Running...');
});
 
app.get('/api/beatles', (req, res) => {
  const data = {
    title: 'The Beatles',
    beatles: [
      {
        'first name': 'John',
        'last name': 'Lennon',
        instrument: 'Guitar',
      },
      {
        'first name': 'Paul',
        'last name': 'McCartney',
        instrument: 'Bass Guitar',
      },
      {
        'first name': 'George',
        'last name': 'Harrison',
        instrument: 'Lead Guitar',
      },
      {
        'first name': 'Ringo',
        'last name': 'Starr',
        instrument: 'Drums',
      },
      {
        'first name': 'Stag',
        'last name': 'Beetle',
        instrument: 'Mandible Harp',
      },
    ],
  };
  res.json(data);
});
 
app.listen(PORT, () => {
  console.log(`Server listening at http://localhost:${PORT}/api.`);
});
 
export default app;

If you go back to http://localhost:5000/api/beatles one last time, then you will see that unlike the last time we added a Beatle, our new beatle has been added to our API route without having to stop our server!

Conclusion

Note, in a typical express server, you wouldn't have your data sitting directly in your route like we did here.

The full code repository can be found at github.com/benjamin-chavez/node-pg-knex-passport-template.

If you found this post useful, then stay tuned for more posts as I document my journey building a multi-vendor marketplace for music producers.

Contact