Express Typescript example
Tags: express, typescript, webdev, beginners
Published: 2023-08-02 02:08:27

<a href="https://expressjs.com/">Express</a> is one of the most popular web frameworks for Node.js that supports routing, middleware, view system... In this tutorial, I will show you how to build Node.js Rest Api example using Express and Typescript.

Related Posts:
- <a href="https://www.bezkoder.com/typescript-orm-mysql/">Node.js Typescript Express with MySQL example</a>
- <a href="https://www.bezkoder.com/typescript-orm-postgres/">Node.js Typescript Express with Postgres example</a>

<h2>Express Typescript example</h2>
We will build Node.js Rest Api using Typescript that handles GET/POST/PUT/DELETE Http requests.

First, we start with an Express web server. Next, we write the controller. Then we define routes for handling all CRUD operations:

The following table shows overview of the Rest APIs that will be exported:
<div class="table-responsive">
<table class="table table-hover  table table-hover" width="100%">
<thead>
<tr>
<th>Methods</th>
<th>Urls</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>api/tutorials</td>
<td>get all Tutorials</td>
</tr>
<tr>
<td>GET</td>
<td>api/tutorials/:id</td>
<td>get Tutorial by <code>id</code></td>
</tr>
<tr>
<td>POST</td>
<td>api/tutorials</td>
<td>add new Tutorial</td>
</tr>
<tr>
<td>PUT</td>
<td>api/tutorials/:id</td>
<td>update Tutorial by <code>id</code></td>
</tr>
<tr>
<td>DELETE</td>
<td>api/tutorials/:id</td>
<td>remove Tutorial by <code>id</code></td>
</tr>
</tbody>
</table>
</div>

Finally, we're gonna test the Express Typescript Rest Api using Postman.

Our project structure will be like this:

<img src="https://www.bezkoder.com/wp-content/uploads/express-typescript-example-project.png" alt="express-typescript-example-project" width="210" height="360" class="alignnone size-full wp-image-15698" />

<h2>Create Node.js Typescript application</h2>
Open terminal/console, then create a folder for our application:

```
$ mkdir express-typescript-example
$ cd express-typescript-example
```

Initialize the Node.js application with a <em>package.json</em> file:
```
npm init

package name: (express-typescript-example) express-typescript-example
version: (1.0.0)
description: Rest API using Node.js, TypeScript, Express
entry point: (index.js) server.js
test command:
git repository:
keywords: nodejs, typescript, express, restapi, rest api, crud
author: bezkoder
license: (ISC)
About to write to D:\Projects\NodeTs\node-js-typescript-express-mysql\package.json:

{
  "name": "express-typescript-example",
  "version": "1.0.0",
  "description": "Rest API using Node.js, TypeScript, Express",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "nodejs",
    "typescript",
    "express",
    "restapi",
    "rest",
    "api",
    "crud"
  ],
  "author": "bezkoder",
  "license": "ISC"
}

Is this OK? (yes)
```

<h2>Add Express and Typescript into Node.js Project</h2>
We need to install necessary modules: <code>express</code>, <code>typescript</code>, <code>cors</code>, <code>ts-node</code>, <code>@types/node</code>, <code>@types/express</code> and <code>@types/cors</code>.

Run the command:
```
npm install typescript ts-node @types/node @types/express @types/cors --save-dev
npm install express cors
```

The <em>package.json</em> file should look like this:
```json
{
  "name": "express-typescript-example",
  "version": "1.0.0",
  "description": "Rest API using Node.js, TypeScript, Express",
  "main": "server.ts",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "express",
    "typescript",
    "rest",
    "api",
    "restapi",
    "node",
    "nodejs",
    "crud"
  ],
  "author": "bezkoder",
  "license": "ISC",
  "devDependencies": {
    "@types/cors": "^2.8.13",
    "@types/express": "^4.17.17",
    "@types/node": "^20.3.3",
    "ts-node": "^10.9.1",
    "typescript": "^5.1.6"
  },
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.18.2"
  }
}
```

Next, we generate a <em>tsconfig.json</em> file with command:
```
./node_modules/.bin/tsc --init
```

Open <em>tsconfig.json</em> and modify the content like this:
```json
{
  "compilerOptions": {
    /* Language and Environment */
    "target": "es2016",                               /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    "experimentalDecorators": true,                   /* Enable experimental support for legacy experimental decorators. */
    "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */

    /* Modules */
    "module": "commonjs",                             /* Specify what module code is generated. */
    "resolveJsonModule": true,                        /* Enable importing .json files. */

    /* Emit */
    "outDir": "./build",                              /* Specify an output folder for all emitted files. */

    /* Interop Constraints */
    "esModuleInterop": true,                          /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
    "forceConsistentCasingInFileNames": true,         /* Ensure that casing is correct in imports. */

    /* Type Checking */
    "strict": true,                                   /* Enable all strict type-checking options. */

    /* Completeness */
    "skipLibCheck": true                              /* Skip type checking all .d.ts files. */
  }
}
```

To work with TypeScript, we need TypeScript compiler (<strong>tsc</strong>), which converts TypeScript code into JavaScript (inside <code>./build</code> folder). TypeScript files have the <strong>.ts</strong> extension. Once compiled to JavaScript, we can run the resulting JavaScript files using a JavaScript runtime environment or include them in web applications.

So we modify <code>"scripts"</code> property of <em>package.json</em> file by adding <code>build</code>, <code>dev</code> and <code>start</code> like this:
```json
{
  ...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc",
    "dev": "node ./build/server.js",
    "start": "tsc && npm run dev"
  }
  ...
}
```

<h2>Create Express Typescript server</h2>
In <strong>src</strong> folder, create <em>index.ts</em> file that export <code>Server</code> class.

```ts
import express, { Application } from "express";
import cors, { CorsOptions } from "cors";

export default class Server {
  constructor(app: Application) {
    this.config(app);
  }

  private config(app: Application): void {
    const corsOptions: CorsOptions = {
      origin: "http://localhost:8081"
    };

    app.use(cors(corsOptions));
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));
  }
}
```

What we do are:
- import <code>express</code>, and <code>cors</code> modules:
<ul>
	<li>Express is for building the Rest Apis</li>
	<li><a href="https://www.npmjs.com/package/cors">cors</a> provides Express middleware to enable CORS with various options.</li>
</ul>
- define <code>constructor()</code> method that receives Express <code>Application</code> object as parameter.
- in <code>constructor()</code>, we call <code>config()</code> method that adds body-parser (<code>json</code> and <code>urlencoded</code>) and <code>cors</code> middlewares using <code>app.use()</code> method. Notice that we set origin: <code>http://localhost:8081</code>.

We continue to create <em>server.ts</em> outside the <strong>src</strong> folder.

```ts
import express, { Application } from "express";
import Server from "./src/index";

const app: Application = express();
const server: Server = new Server(app);
const PORT: number = process.env.PORT ? parseInt(process.env.PORT, 10) : 8080;

app
  .listen(PORT, "localhost", function () {
    console.log(`Server is running on port ${PORT}.`);
  })
  .on("error", (err: any) => {
    if (err.code === "EADDRINUSE") {
      console.log("Error: address already in use");
    } else {
      console.log(err);
    }
  });
```

In the code, we:
- create an Express application using <code>express()</code>.
- initialize a <code>Server</code> object with an <code>Application</code> object
- listen on port 8080 for incoming requests.

Let's run the app with command: <code>npm run start</code>.
```
$ npm run start

> express-typescript-example@1.0.0 start
> tsc && npm run dev

> express-typescript-example@1.0.0 dev
> node ./build/server.js

Server is running on port 8080.
```

<h2>Working with Express Router in Typescript</h2>
To handle HTTP requests, we create a new <code>Router</code> object using <code>express.Router()</code> function.

In <strong>src</strong>/<strong>routes</strong> folder, create <em>home.routes.ts</em> file that exports <code>Router</code> object.
```ts
import { Router } from "express";
import { welcome } from "../controllers/home.controller";

class HomeRoutes {
  router = Router();

  constructor() {
    this.intializeRoutes();
  }

  intializeRoutes() {
    this.router.get("/", welcome);
  }
}

export default new HomeRoutes().router;
```

<code>router.get("/", welcome)</code> is for handling Http GET requests with <code>welcome</code> as handler function.

In <strong>src</strong>/<strong>controllers</strong>/<em>home.controller.ts</em>, we export <code>welcome</code> function.
```ts
import { Request, Response } from "express";

export function welcome(req: Request, res: Response): Response {
  return res.json({ message: "Welcome to bezkoder application." });
}
```

Next we create <code>Routes</code> class in <strong>src</strong>/<strong>routes</strong>/<em>index.ts</em>.
```ts
import { Application } from "express";
import homeRoutes from "./home.routes";

export default class Routes {
  constructor(app: Application) {
    app.use("/api", homeRoutes);
  }
}
```

Then we import <code>Routes</code> into <code>Server</code> class's <code>constructor()</code> method and initialize a new <code>Routes</code> object.
```ts
// ...
import Routes from "./routes";

export default class Server {
  constructor(app: Application) {
    this.config(app);
    new Routes(app);
  }

  private config(app: Application): void {
    // ...
  }
}
```

Let's stop and re-start the server. Open your browser with url <a href="http://localhost:8080/api">http://localhost:8080/api</a>, you will see:

<img src="https://www.bezkoder.com/wp-content/uploads/express-typescript-example-server.png" alt="express-typescript-example-server" width="390" height="120" class="alignnone size-full wp-image-15705" />

<h2>Handling GET-POST-PUT-DELETE requests with Express Typescript</h2>
Now we implement more routes to <code>Routes</code> class that follows APIs:

| Methods | Urls | Actions |
| --- | --- | --- |
| GET | api/tutorials | get all Tutorials |
| GET | api/tutorials/:id | get Tutorial by `id` |
| POST | api/tutorials | add new Tutorial |
| PUT | api/tutorials/:id | update Tutorial by `id` |
| DELETE | api/tutorials/:id | remove Tutorial by `id` |

In <strong>src</strong>/<strong>routes</strong>/<em>index.ts</em>, add middleware function for <code>"/api/tutorials"</code> endpoint.
```ts
import { Application } from "express";
import homeRoutes from "./home.routes";
import tutorialRoutes from "./tutorial.routes";

export default class Routes {
  constructor(app: Application) {
    app.use("/api", homeRoutes);
    app.use("/api/tutorials", tutorialRoutes);
  }
}
```

We continue to define the above <code>TutorialRoutes</code> class which initializes a <code>TutorialController</code> object that provides CRUD operation methods. It exports <code>Router</code> object. 

<strong>src</strong>/<strong>routes</strong>/<em>tutorial.routes.ts</em>
```ts
import { Router } from "express";
import TutorialController from "../controllers/tutorial.controller";

class TutorialRoutes {
  router = Router();
  controller = new TutorialController();

  constructor() {
    this.intializeRoutes();
  }

  intializeRoutes() {
    // Create a new Tutorial
    this.router.post("/", this.controller.create);

    // Retrieve all Tutorials
    this.router.get("/", this.controller.findAll);

    // Retrieve a single Tutorial with id
    this.router.get("/:id", this.controller.findOne);

    // Update a Tutorial with id
    this.router.put("/:id", this.controller.update);

    // Delete a Tutorial with id
    this.router.delete("/:id", this.controller.delete);
  }
}

export default new TutorialRoutes().router;
```

In <strong>src</strong>/<strong>controllers</strong>/<em>tutorial.controller.ts</em>, we define and export <code>TutorialController</code> class that has <code>create</code>, <code>findAll</code>, <code>findOne</code>, <code>update</code>, <code>delete</code> methods.

```ts
import { Request, Response } from "express";

export default class TutorialController {
  async create(req: Request, res: Response) {
    try {
      res.status(201).json({
        message: "create OK",
        reqBody: req.body
      });
    } catch (err) {
      res.status(500).json({
        message: "Internal Server Error!"
      });
    }
  }

  async findAll(req: Request, res: Response) {
    try {
      res.status(200).json({
        message: "findAll OK"
      });
    } catch (err) {
      res.status(500).json({
        message: "Internal Server Error!"
      });
    }
  }

  async findOne(req: Request, res: Response) {
    try {
      res.status(200).json({
        message: "findOne OK",
        reqParamId: req.params.id
      });
    } catch (err) {
      res.status(500).json({
        message: "Internal Server Error!"
      });
    }
  }

  async update(req: Request, res: Response) {
    try {
      res.status(200).json({
        message: "update OK",
        reqParamId: req.params.id,
        reqBody: req.body
      });
    } catch (err) {
      res.status(500).json({
        message: "Internal Server Error!"
      });
    }
  }

  async delete(req: Request, res: Response) {
    try {
      res.status(200).json({
        message: "delete OK",
        reqParamId: req.params.id
      });
    } catch (err) {
      res.status(500).json({
        message: "Internal Server Error!"
      });
    }
  }
}
```

<h2>Run and Check</h2>
Run the Node.js Express Typescript Rest APIs with command:
<code>npm run start</code>

- GET <code>http://localhost:8080/api/tutorials</code>

<img src="https://www.bezkoder.com/wp-content/uploads/express-typescript-example-get.png" alt="express-typescript-example-get" width="440" height="230" class="alignnone size-full wp-image-15710" />

- GET <code>http://localhost:8080/api/tutorials/[id]</code>

<img src="https://www.bezkoder.com/wp-content/uploads/express-typescript-example-get-one.png" alt="express-typescript-example-get-one" width="430" height="250" class="alignnone size-full wp-image-15712" />

- POST <code>http://localhost:8080/api/tutorials</code>

<img src="https://www.bezkoder.com/wp-content/uploads/express-typescript-example-post.png" alt="express-typescript-example-post" width="440" height="434" class="alignnone size-full wp-image-15711" />

- PUT <code>http://localhost:8080/api/tutorials/[id]</code>

<img src="https://www.bezkoder.com/wp-content/uploads/express-typescript-example-put.png" alt="express-typescript-example-put" width="440" height="490" class="alignnone size-full wp-image-15714" />

- DELETE <code>http://localhost:8080/api/tutorials/[id]</code>

<img src="https://www.bezkoder.com/wp-content/uploads/express-typescript-example-delete.png" alt="express-typescript-example-delete" width="428" height="250" class="alignnone size-full wp-image-15715" />

<h2>Conclusion</h2>
Today, we've learned how to create Node.js Rest Apis with an Express Typescript web server. We also know way to write a controller and define routes for handling all CRUD operations.

Happy learning! See you again.

<h2>Further Reading</h2>
<ul>
	<li><a href="http://expressjs.com/en/guide/routing.html">Express.js Routing</a></li>
	<li><a href="https://www.npmjs.com/package/express">https://www.npmjs.com/package/express</a></li>
</ul>

File Upload Rest API:
- <a href="https://www.bezkoder.com/node-js-express-file-upload/">Node.js Express File Upload Rest API example using Multer</a>
- <a href="https://www.bezkoder.com/google-cloud-storage-nodejs-upload-file/">Google Cloud Storage with Node.js: File Upload example</a>

<h2>Source code</h2>
You can find the complete source code for this example on <a href="https://github.com/bezkoder/express-typescript-example">Github</a>.

With Database:
- <a href="https://www.bezkoder.com/typescript-orm-mysql/">Node.js Typescript Express with MySQL example</a>
- <a href="https://www.bezkoder.com/typescript-orm-postgres/">Node.js Typescript Express with Postgres example</a>