Simplifying DTO Management In Express.js with Class-Transformer
Tags: typescript, javascript, express
Published: 2023-03-05 04:12:24

Data Transfer Objects (DTOs) are an essential concept in modern software development. They are used to transfer data between different layers of an application or between different applications. A DTO is a simple object that carries data between different layers of an application, such as between a client and a server. DTOs are often used to reduce the amount of data sent between the client and server and to provide a clear separation of concerns.

To make the process of managing DTOs easier, we can use the [class-transformer](https://github.com/typestack/class-transformer) library. Class-transformer is a TypeScript library that helps to convert plain JavaScript objects to class instances and vice versa. In this article, we will explore how to use class-transformer in Express.js to manage DTOs.

### Installing Class-transformer

1. To get started, we need to install the `class-transformer` library. Open a terminal window and navigate to your project directory. Then run the following command:

```bash
npm install class-transformer
```

1. We also need to install `reflect-metadata` as it is a prerequisite of `class-transformer` library.

```bash
 npm install reflect-metadata
```

### Creating a DTO Class

The first step in using class-transformer is to create a DTO class. A DTO class is a TypeScript class that represents the data we want to transfer between different layers of our application.

Here's an example of a simple DTO class that represents a user:

```tsx
import { Expose } from 'class-transformer';

export class UserDTO {
  @Expose()
  firstName!: string;

  @Expose()
  lastName!: string;

  @Expose()
  email!: string;

  @Expose()
  age!: number;

  @Exclude()
  password!: string;
}
```

In the example above, we've defined a DTO class called UserDTO that has five properties: firstName, lastName, email, age and password. We've also used the `Expose` decorator from `class-transformer` to specify that each property should be included and `Exclude` decorator to specify that the property should not be included when we convert an instance of this class to a plain JavaScript object.

### Converting an Object to a DTO

To convert an object to a DTO, we can simply create an instance of the DTO class and pass in the object as a parameter. Class-transformer will automatically map the object's properties to the corresponding properties in the DTO class.

Here's an example of how to convert an object to a UserDTO:

```tsx
import { plainToClass } from 'class-transformer';
import { UserDTO } from './user.dto';

const user = {
  firstName: 'John',
  lastName: 'Doe',
  email: 'johndoe@example.com',
  age: 30,
  password: "secretpass", 
  confirmPassword: "secretpass"
};

const userDTO = plainToClass(UserDTO, user, { excludeExtraneousValues: true });
console.log(userDTO);
```

In the example above, we've created an object called user that represents a user. We've then used the `plainToClass` function from class-transformer to convert the user object to a UserDTO instance. Finally, we've logged the UserDTO instance to the console.

### Converting request bodies

One of the most common use cases for class-transformer is converting request bodies. When we receive data from an API client, it usually comes in the form of a JSON object. We can use class-transformer to convert this JSON object to an instance of our DTO class.

```tsx
import { plainToClass } from 'class-transformer';
import { Request, Response } from 'express';
import { UserDTO } from './dto/user.dto';

app.post('/users', async (req: Request, res: Response) => {
  const userDTO = plainToClass(UserDTO, req.body. { excludeExtraneousValues: true });

  // Create user in database...
});
```

### Converting API responses

We can also use`class-transformer` to convert API responses and provide the specific shape of data which the API client needs. Here is an example of how we can do this:

```tsx
export class UserResponseDTO{
  @Expose()
  firstName!: string;

  @Expose()
  lastName!: string;

  @Expose()
  email!: string;

  @Expose()
  age!: number;

  @Expose({ name: 'fullName' })
  getFullName() {
    return this.firstName + ' ' + this.lastName;
  }
}

app.get('/users/:id', async (req, res) => {
  const id = req.params.id;
  const user = UserModel.findById(id); // full user object
	const userResponseDTO = plainToClass(UserDTO, req.body. { excludeExtraneousValues: true });
  res.json(userResponseDTO);
});
```

Here the response will be like this: 

```jsx
{
 firstName: "Mostafizur",
 lastName: "Rahman",
 email: "mostafizur@example.com",
 age: "27",
 fullName: "Mostafizur Rahman"
}
```

### Converting a DTO to an Object

To convert a DTO to an object, we can use `classToPlain` function from class-transformer to convert the a UserDTO instance to a user object. Class-transformer will automatically convert the DTO instance to a plain JavaScript object.

Here's an example of how to convert a UserDTO instance to an object:

```tsx
import { classToPlain } from 'class-transformer';
import { UserDTO } from './user.dto';

const userDTO = new UserDTO();
userDTO.firstName = 'John';
userDTO.lastName = 'Doe';
userDTO.email = 'johndoe@example.com';
userDTO.age = 30;

const user = classToPlain(userDTO);
console.log(user);
```

In the example above, we've created a UserDTO instance called `userDTO`. We've then set the values of its properties. Finally, we've logged the plain user object to the console.

### Conclusion

Class-transformer is a powerful tool for managing data transfer objects. In this article I have shown an high level overview of the `class-transformer` library. To learn more about this library please checkout out their official documentation [here](https://github.com/typestack/class-transformer).