DEV Community

Carlos Daniel Ortega Hernandez
Carlos Daniel Ortega Hernandez

Posted on

Build a Node.js and Express.js API with Typescript.

Structure of files

├── build
├── node_modules
├── src
│   ├── data
│   │   └── tasks.json
│   ├── routes
│   │   └── task-routes.ts
│   ├── services
│   │   └── task-service.ts
│   ├── index.ts
|   └── types.d.ts
├── .gitignore
├── package-lock.json
├── package.json
└── tsconfig.json
Enter fullscreen mode Exit fullscreen mode

Initialize the project

First, we need to initialize the project.

npm init -y
Enter fullscreen mode Exit fullscreen mode

Install packages

Install dependencies of the project.

npm install --save express
Enter fullscreen mode Exit fullscreen mode

And install dev dependencies of the project.

npm install --save-dev @types/express typescript ts-node-dev
Enter fullscreen mode Exit fullscreen mode
  • express: is a Node.js web application framework.
  • @types/express: is a TypeScript definition file for the express module.
  • typescript: is a TypeScript compiler.
  • ts-node-dev: is a TypeScript compiler that runs the server with TypeScript.

Add scripts to package.json

Add scripts to package.json.

"scripts": {
    "dev": "ts-node-dev src/index.ts",
    "start": "node build/index.js",
    "tsc": "tsc"
}
Enter fullscreen mode Exit fullscreen mode
  • dev: is a command to run the server with TypeScript.
  • start: is a command to run the server.
  • tsc: is a command to compile the TypeScript code.

Initialize TypeScript

Now initialize TypeScipt:

$ npm run tsc -- --init
Enter fullscreen mode Exit fullscreen mode

This will create a tsconfig.json file, which is a TypeScript configuration file.

Configure TypeScript

For this project, we use the following configuration:

{
    "compilerOptions": {
        "target": "es2016",
        "module": "commonjs",
        "resolveJsonModule": true,
        "outDir": "./build",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true,
        "skipLibCheck": true
    }
}
Enter fullscreen mode Exit fullscreen mode

For to know more about the configuration, please visit TypeScript Configuration.

Create a server

In this project, we will create a server with Express.js.

// src/index.ts
import express from 'express';
const app = express();
const PORT = 3000;

app.use(express.json());

app.get('/', (_req, res) => {
    res.send('Hello World!');
});

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

And compile the server:

$ npm run dev
Enter fullscreen mode Exit fullscreen mode

Add data to the server

For this project we use the following data:

// src/data/tasks.json
[
    {
        "id": 1,
        "title": "Task 1",
        "description": "Description 1",
        "priority": "High",
        "completed": false,
        "createdAt": "2020-01-01"
    },
    {
        "id": 2,
        "title": "Task 2",
        "description": "Description 2",
        "priority": "Low",
        "completed": false,
        "createdAt": "2020-01-02"
    },
    {
        "id": 3,
        "title": "Task 3",
        "description": "Description 3",
        "priority": "Medium",
        "completed": false,
        "createdAt": "2020-01-03"
    },
    {
        "id": 4,
        "title": "Task 4",
        "description": "Description 4",
        "priority": "High",
        "completed": false,
        "createdAt": "2020-01-04"
    },
    {
        "id": 5,
        "title": "Task 5",
        "description": "Description 5",
        "priority": "Low",
        "completed": false,
        "createdAt": "2020-01-05"
    },
    {
        "id": 6,
        "title": "Task 6",
        "description": "Description 6",
        "priority": "Medium",
        "completed": false,
        "createdAt": "2020-01-06"
    },
    {
        "id": 7,
        "title": "Task 7",
        "description": "Description 7",
        "priority": "High",
        "completed": false,
        "createdAt": "2020-01-07"
    },
    {
        "id": 8,
        "title": "Task 8",
        "description": "Description 8",
        "priority": "Low",
        "completed": false,
        "createdAt": "2020-01-08"
    },
    {
        "id": 9,
        "title": "Task 9",
        "description": "Description 9",
        "priority": "Medium",
        "completed": false,
        "createdAt": "2020-01-09"
    }
]
Enter fullscreen mode Exit fullscreen mode

We need to add types to the tasks.json file.

// src/types.d.ts
export type Priority = 'Low' | 'Medium' | 'High';

export interface BaseTask {
    title: string;
    description: string;
    priority: Priority;
    completed: boolean;
    createdAt: string;
}

export interface Task extends BaseTask {
    id: number;
}
Enter fullscreen mode Exit fullscreen mode

Create the services.

And now we need some services to handle the requests.

// src/services/task-services.ts
import tasksData from '../data/tasks.json';
import { Task, BaseTask } from '../types';

const tasks: Task[] = tasksData as Task[];

export const getAllTasks = ():Task[] => tasks;

export const getTask = (id: number):Task | undefined => tasks.find(task => task.id === id);

export const addTask = (task: BaseTask):void => {
    const newTask = { ...task, id: tasks.length + 1 };
    tasks.push(newTask);
};

export const updateTask = (id: number, task: BaseTask):void => {
    const taskIndex = tasks.findIndex(t => t.id === id);
    if (taskIndex > -1) {
        tasks[taskIndex] = { ...tasks[taskIndex], ...task };
    }
};

export const deleteTask = (id: number):void => {
    const taskIndex = tasks.findIndex(t => t.id === id);
    if (taskIndex > -1) {
        tasks.splice(taskIndex, 1);
    }
};
Enter fullscreen mode Exit fullscreen mode

Add a routes to the server

We will add a route to the server.

// src/routes/task-routes.ts
import express from "express";
const router = express.Router();
import {getAllTasks, getTask, addTask, updateTask, deleteTask} from "../services/task-services";
import {BaseTask} from "../types";

router.get('/', (_req, res) => {
    res.send(getAllTasks());
});

router.get('/:id', (req, res) => {
    const {id} = req.params;
    const task = getTask(Number(id));
    if (task) {
        res.send(task);
    } else {
        res.sendStatus(404);
    }
});

router.post('/', (req, res) => {
    const {title, description, priority, completed, createdAt} = req.body;
    const task: BaseTask = {
        title,
        description,
        priority,
        completed,
        createdAt
    };
    addTask(task);
    res.send({message: 'Task added successfully'});
});

router.put('/:id', (req, res) => {
    const {id} = req.params;
    const {title, description, priority, completed, createdAt} = req.body;
    const task: BaseTask = {
        title,
        description,
        priority,
        completed,
        createdAt
    };
    updateTask(Number(id), task);
    res.send({message: 'Task updated'});
});

router.delete('/:id', (req, res) => {
    const {id} = req.params;
    deleteTask(Number(id));
    res.send({message: 'Task deleted'});
});

module.exports = router;

Enter fullscreen mode Exit fullscreen mode

And now we need to add the routes to the server.

// src/index.ts
app.use("/api/tasks", require("./routes/task-routes"));
Enter fullscreen mode Exit fullscreen mode

We have now created a server api that can be used to get tasks, get task, add, update and delete.

Top comments (0)