Why should we use Typescript with NodeJs and Express?
Tags: typescript, node, webdev, express
Published: 2023-03-29 00:05:40


# **Here are some topics I can cover to explain why using Typescript with Node and Express is beneficial :**


### 1. What is Typescript and why is it useful in web development?

### 2. Why You Should Choose Typescript Over JavaScript?

### 3. How to set up TypeScript with Node.js and Express.

### 4. Best practices for using TypeScript with Node.js and Express.


## **1. What is Typescript?**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/auo6sdmxd6b8uin3h5mv.jpg)
- Typescript is a programming language that adds static **typing**, **compiling** and **OOP** to JavaScript. It can be used for both client-side (Front-end Frameworks like **Angular, React and vue**) and server-side applications (**Nodejs**).

## **Why is it useful in web development?**

- It makes our code more secure and robust by preventing many bugs before the code is even shipped.

- It catches problems during code development and integrates wonderfully with code editors like Visual Studio Code.

## 2. Why You Should Choose Typescript Over JavaScript?
Three reasons why you should choose TypeScript over JavaScript

- Typescript is an enhanced version of JavaScript.
- TypeScript makes it easier to write accurate code more quickly and catch bugs prior to runtime.
- TypeScript is more reliable and easier to refactor. This enables developers to avoid errors and do restructure much easier.
- TypeScript is more explicit. It takes our attention to make types explicitly on variables, return type and etc...
- TypeScript is an object-oriented scripting language. These features make it possible for developers to write more structured, maintainable, and scalable code.
- Dependent language (compiles to JavaScript).

## **3. How to set up TypeScript with Node.js and Express.**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/avt52r9dimw68ot4njlr.png) 

###Steps to setup Nodejs typescript project : 

###1. Install Node and npm :

Make sure that you installed **Node** on your device  
`node -v`  to detect whether you have installed the **Node** or not. If you installed node output is `v18.15.0` or any version. If you didn't install node output will be `node: command not found.` 

You need to install node by going to **Nodejs website** [NodeJS website](https://nodejs.org/en)

Make sure that you installed **Node Package Manager npm** on your device `npm -v`  to detect whether you have installed the npm or not. If you installed npm output is `9.6.1` or any version. If you didn't install npm output will be `npm: command not found.` 

###2. Create a New Project Folder.

###3. Start running npm in your project folder :

- Open a terminal.
- Run the command `npm init -y` to initial npm and install packages.

###4. Add TypeScript as a dev dependency
`npm install typescript --save-dev`

###5. Install ambient Node.js types for TypeScript :

```
npm install @types/node --save-dev
```
###6. Create `tsconfig.json` :

```
npx tsc --init
```
- Copy this in `tsconfig.json`

```
{
  "compilerOptions": {
    "target": "es5",                          
    "module": "commonjs",                    
    "lib": ["es6"],                     
    "allowJs": true,
    "outDir": "dist",                          
    "rootDir": ".",
    "strict": true,         
    "noImplicitAny": true,
    "esModuleInterop": true,
    "resolveJsonModule": true
  }
}
```
###7. To reload server :

```
npm install nodemon ts-node -D
```
- **nodemon** which is used to watch for changes to our code and automatically restart when a file is changed.
- **ts-node** for running TypeScript code directly without having to wait for it be compiled.

- Add `nodemon.json` file and write the following in it: 

```
{
    "watch": ["./"],
    "ext": ".ts,.js",
    "ignore": [],
    "exec": "npx ts-node index.ts"
  }
```
###8. Write in **scripts** in **package.json**, to use it in running server : 
```
  "scripts": {
    "start:dev": "npx nodemon"
  },
```
###9. Create our first TypeScript file `index.ts`.

###10. Create simple server using **express** framework 
- First install express and @types/express 

```
npm i express
npm i @types/express -D
```
- Write in **index.ts** 

```
import express,{ Application, Router ,Request, Response} from "express";

const app :Application = express();
var router :Router= require('express').Router();
const port :number = 3000;
app.use(router);

router.get("/", function (req:Request, res:Response) : void {
    res.send("<h1>Hello, I'm Ali Ahmed. I'm Software Engineer</h1>");
  });
app.listen(port, () => {
    console.log(`Server Running here 👉 http://localhost:${port}`);
})

```
###11. Finally run this command to **run server**

```
npm run start:dev 
```

Output will be : 

```
> testnodewithtypescript@1.0.0 start:dev
> npx nodemon

[nodemon] 2.0.22
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): **/*
[nodemon] watching extensions: ts,js
[nodemon] starting `npx ts-node index.ts`
Server Running here 👉 http://localhost:3000
```

## **4. Best practices for using TypeScript with Node.js and Express.** 
###1. Use strict typing: 

```
{
  "compilerOptions": {
    "strict": true
  }
}
```

- One of the key advantages of TypeScript is that it provides strong typing. 
- Strict mode activates 2 main compiler options:
     1. **noImplicitAny** : explicit anys are not accepted by TypeScript.
     2. **strictNullChecks** : will ask to tell when a value can be null.

###2. Use interfaces:

- Interfaces are a powerful feature of TypeScript that allow you to define a contract for an object's properties and methods. This can help you catch errors at compile-time and make your code more organized and maintainable. Use interfaces to define the shape of your **data models** and **API responses**. By using an interface to define the shape of the user object, you can **catch errors at compile-time if you try to assign the wrong type of data to a property**, or if you forget to include a **required property**. This can help you write more reliable code and avoid common bugs.
 

```
// In API responses
import { Request, Response } from 'express';

interface User {
    id: number;
    name: string;
    email: string;
    socialMediaProfile:string[]
    createdAt: Date;
  }

function getUser(req: Request, res: Response): void {
    const user: User = {
        id: 1,
        name: 'Ali Ahmed',
        email: 'aliahmedfathi37@gmail.com',
        socialMediaProfile:[
            "linkedin.com/in/ali-ahmed-fathi", // linkedin profile
            "https://github.com/AliFathy-1999", //Github profile
        ],
        createdAt: new Date(),
      };
}
```

```
//In Data models:

interface IUserModel{
    fname:String,
    lname:String,
    email:String,
    password:String,
}
const schema= new Schema<IUserModel>({
    fname:{
        type:String,
        required:true,
        trim:true,
        minlength:3,
        maxlength:20
    },
    lname:{
        type:String,
        required:true,
        trim:true,
        minlength:3,
        maxlength:20
    },
    email:{
        type:String,
        required:true,
        unique:true,
    },
    password:{
        type:String,
        required:true,
        trim:true,
        minlength:6,
    },
},{
    timestamps:true  //createdAt, updatedAt
});
```
###3. Use Generics:
It helps developers to write more **reusable and flexible code**. Use generics to write **functions and classes that can work with different types of data.**

```
/*
Let's say you have a function that takes an array of objects and returns an array of a specific property from each object. You can use generics to make this function work with any type of object and any type of property.
*/
  function myGeneric<T, K extends keyof T>(items: T[], key: K): T[K][] {
    return items.map(item => item[key]);
  }
  const users: User[] = [
    { id: 1, name: 'Mustafa Mahmoud',socialMediaProfile:["",""], email: 'Mustafa@hotmail.com',createdAt:new Date },
    { id: 2, name: 'Bassem Mahmoud',socialMediaProfile:["",""], email: 'Bassem@hotmail.com',createdAt:new Date },
  ];
  
  const names = myGeneric(users, 'name'); // ['Mustafa Mahmoud', 'Bassem Mahmoud']
```

###4. Use Async/Await:
- API endpoint that **fetches some data** from a database using an asynchronous function.
``` 
  const getUserByEmail = async (req: Request, res: Response): Promise<void> =>{
    try {
        const { body: { email } } = req
      const data = await User.findOne({email});
      res.json(data);
    } catch (err) {
      res.status(500).json({ error: 'Internal server error' });
    }
  }
```
##Finally, I want to thank you for taking the time to read my article and I hope this article is useful for you :).