DEV Community

Cover image for Express Typescript example
Tien Nguyen
Tien Nguyen

Posted on • Originally published at bezkoder.com

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)