Node.js and Express.js with TypeScript

Prerequisites:

Installation

npm install -g npm                  // node install
npm install typescript --save-dev // typescript install
console.log(‘Something Went Wrong’);
Regular JS code in .ts file works fine
node app.ts
var age:number;age = 25;console.log(age);
TypeScript code has thrown an error
tsc app.ts

Setting up Node and TS environment:

  1. Node environment:
npm init --yes    // creates package.json file
npm install express body-parser nodemon // dependent packages
Node — package.json
tsc --init.    // creates tsconfig.ts file
{  "compilerOptions": {    "target": "ES2018",                                "module": "commonjs",                              "moduleResolution": "node",    "outDir": "./dist",  /* js files lives here */    "rootDir": "./src",  /* ts file resides here */}
tsconfig.ts
const express = require('express');const app = express();app.listen(3000);  // PORT
npm install @types/nodenpm install @types/express
Error is gone
"scripts": {  "start": "nodemon dist/app.js"},
tsc --watch      // this starts TypeScript compiler
npm start // this starts Node server
Getting this error indicates Node server is running

Creating ToDo App using RESTful API:

import { Router } from 'express';// Old node way// const express = require('express');// const Router = express.Router;const router = Router();router.post('/');router.get('/');router.patch('/:id');router.delete('/:id');export default router;
import express, {Request, Response, NextFunction} from 'express';import todoRoutes from './routes/todos';   // Route connectedconst app = express();app.use('/todos', todoRoutes);// This means all route path preceed this path
// Below route is trigerred when any error is is thrown
app.use((err: Error, req: Request, res:Response, next: NextFunction) => { res.status(500).json({message: err.message});});app.listen(3000);
import { RequestHandler } from 'express';  export const createTodos:RequestHandler = (req, res, next) => {};
export class Todo {   constructor(public id: string, public text: string) {}}
export class Todo {  id: string;  text: string;  constructor(id:string, text: string) {    this.id = id;    this.text = text;  }}
export class Todo {  constructor(public id: string, public text: string) {}}
import { RequestHandler, response } from 'express';import { Todo } from '../models/todos';const TODOS: Todo[] = [];export const createTodos:RequestHandler = (req, res, next) => {  const text = (req.body as { text:string } ).text; // making it  string type  // const text = req.body.text; //typeScript is not allowing :any type  const id = Math.random().toString();  const newTodo = new Todo(id, text);  TODOS.push(newTodo);  res.status(201).json({message: 'Todo created successfully',   createdTodo: newTodo});};
import { Router } from 'express';import { createTodos } from '../controllers/todos';router.post('/', createTodos);   // CREATE Routeexport default router;
import express, {Request, Response, NextFunction} from 'express';......const app = express();app.use(json());  // registering this middleware for accepting json requestsapp.use('/todos', todoRoutes); // All route must preceed with this path
...
app.listen(3000);
Response is Successful
url: http://localhost:3000/todos/body:{
"text": "Tech meetups" // Your ToDO data to save
}
// body type raw in json format
export const getTodos:RequestHandler = (req, res, next) => {   res.status(200).json({"todos": TODOS});};
router.get('/', getTodos);
export const updateTodos: RequestHandler<{id: string}> = (req, res, next) => {  const todoId = req.params.id;  const updatedText = (req.body as { text:string }).text;  const todoIndex = TODOS.findIndex(x => x.id === todoId);  if(todoIndex < 0) {    throw new Error('Could not find todo!');  }  TODOS[todoIndex] = new Todo(TODOS[todoIndex].id, updatedText);  res.status(201).json({message: 'Todo updated successfully', updateTodo:  TODOS[todoIndex]});};
router.patch('/:id', updateTodos);
Get request — taking id whose data need to update
Update request — passing id in url to update and data to update in body
Get Request — Running it again to see the updated result
export const deleteTodos: RequestHandler<{id: string}> = (req, res, next) => {  const todoId = req.params.id;  const todoIndex = TODOS.findIndex(x => x.id === todoId);  if(todoIndex < 0) {    throw new Error('Could not find todo!');  }  console.log( TODOS[todoIndex].text, typeof todoIndex );  const deletedData = {id: TODOS[todoIndex].id, text:   TODOS[todoIndex].text};
TODOS.splice(todoIndex, 1);
res.status(201).json({message: `${deletedData.id}: ${deletedData.text} deleted successfully`})}
router.delete('/:id', deleteTodos);

Summary:

Closing thoughts:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Amir Mustafa

Amir Mustafa

JavaScript Specialist | Consultant | YouTuber 🎬. | AWS ☁️ | Docker 🐳 | Digital Nomad | Human. Connect with me on https://www.linkedin.com/in/amirmustafa1/