DEV Community

Cover image for Express Typescript example
Tien Nguyen
Tien Nguyen

Posted on • Originally published at bezkoder.com

14 1

Express Typescript example

Express 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:

Express Typescript example

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:

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

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

Our project structure will be like this:

express-typescript-example-project

Create Node.js Typescript application

Open terminal/console, then create a folder for our application:



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


Enter fullscreen mode Exit fullscreen mode

Initialize the Node.js application with a package.json 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)


Enter fullscreen mode Exit fullscreen mode

Add Express and Typescript into Node.js Project

We need to install necessary modules: express, typescript, cors, ts-node, @types/node, @types/express and @types/cors.

Run the command:



npm install typescript ts-node @types/node @types/express @types/cors --save-dev
npm install express cors


Enter fullscreen mode Exit fullscreen mode

The package.json file should look like this:



{
  "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"
  }
}


Enter fullscreen mode Exit fullscreen mode

Next, we generate a tsconfig.json file with command:



./node_modules/.bin/tsc --init


Enter fullscreen mode Exit fullscreen mode

Open tsconfig.json and modify the content like this:



{
  "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. */
  }
}


Enter fullscreen mode Exit fullscreen mode

To work with TypeScript, we need TypeScript compiler (tsc), which converts TypeScript code into JavaScript (inside ./build folder). TypeScript files have the .ts 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 "scripts" property of package.json file by adding build, dev and start like this:



{
  ...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc",
    "dev": "node ./build/server.js",
    "start": "tsc && npm run dev"
  }
  ...
}


Enter fullscreen mode Exit fullscreen mode

Create Express Typescript server

In src folder, create index.ts file that export Server class.



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 }));
  }
}


Enter fullscreen mode Exit fullscreen mode

What we do are:

  • import express, and cors modules:
    • Express is for building the Rest Apis
    • cors provides Express middleware to enable CORS with various options.
  • define constructor() method that receives Express Application object as parameter.
  • in constructor(), we call config() method that adds body-parser (json and urlencoded) and cors middlewares using app.use() method. Notice that we set origin: http://localhost:8081.

We continue to create server.ts outside the src folder.



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);
    }
  });


Enter fullscreen mode Exit fullscreen mode

In the code, we:

  • create an Express application using express().
  • initialize a Server object with an Application object
  • listen on port 8080 for incoming requests.

Let's run the app with command: npm run start.



$ 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.


Enter fullscreen mode Exit fullscreen mode

Working with Express Router in Typescript

To handle HTTP requests, we create a new Router object using express.Router() function.

In src/routes folder, create home.routes.ts file that exports Router object.



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;


Enter fullscreen mode Exit fullscreen mode

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

In src/controllers/home.controller.ts, we export welcome function.



import { Request, Response } from "express";

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


Enter fullscreen mode Exit fullscreen mode

Next we create Routes class in src/routes/index.ts.



import { Application } from "express";
import homeRoutes from "./home.routes";

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


Enter fullscreen mode Exit fullscreen mode

Then we import Routes into Server class's constructor() method and initialize a new Routes object.



// ...
import Routes from "./routes";

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

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


Enter fullscreen mode Exit fullscreen mode

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

express-typescript-example-server

Handling GET-POST-PUT-DELETE requests with Express Typescript

Now we implement more routes to Routes 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 src/routes/index.ts, add middleware function for "/api/tutorials" endpoint.



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);
  }
}


Enter fullscreen mode Exit fullscreen mode

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

src/routes/tutorial.routes.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;


Enter fullscreen mode Exit fullscreen mode

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



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!"
      });
    }
  }
}


Enter fullscreen mode Exit fullscreen mode

Run and Check

Run the Node.js Express Typescript Rest APIs with command:
npm run start

express-typescript-example-get

express-typescript-example-get-one

express-typescript-example-post

express-typescript-example-put

express-typescript-example-delete

Conclusion

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.

Further Reading

File Upload Rest API:

Source code

You can find the complete source code for this example on Github.

With Database:

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️