Create a Mapper
Installation
First step is to install @automapper/* via npm or yarn
npm i @automapper/core @automapper/classes reflect-metadata
yarn add @automapper/core @automapper/classes reflect-metadata
info
- We are using
@automapper/classesfor this tutorial. Check Installation for more details. - The rest of the tutorial will apply to
@automapper/classesonly. If you're using@automapper/pojos, please check POJOs Strategy
Next, let's adjust the tsconfig of your project. Make sure that you have the following options:
{
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true
}
note
skipLibCheck is required if your TypeScript version is below 4.0
Create your first Mapper
Now that you have everything installed and configured, let's start creating the Mapper.
import { createMapper } from '@automapper/core';
import { classes } from '@automapper/classes';
// Create and export the mapper
export const mapper = createMapper({
strategyInitializer: classes(),
});
tip
A typical project should only have a singleton Mapper with a certain MappingStrategy.
info
createMapper() accepts a CreateMapperOptions which allows to customize the Mapper. Read more at createMapper() API
Metadata Discovery
For AutoMapper to do the Auto part, you need to tell AutoMapper about your models. In other words, let AutoMapper know what your models have, what properties, what types those properties have.
With @automapper/classes, you will use @AutoMap() decorator to do so. Let's bring back the models
- user.entity.ts
- user.dto.ts
export class User {
@AutoMap()
firstName: string;
@AutoMap()
lastName: string;
@AutoMap()
username: string;
password: string; // <- we purposely left this one out because we don't want to map "password"
@AutoMap(() => Bio)
bio: Bio;
}
export class Bio {
@AutoMap(() => Job)
job: Job;
@AutoMap()
birthday: Date;
@AutoMap()
avatarUrl: string;
}
export class Job {
@AutoMap()
title: string;
@AutoMap()
salary: number;
}
export class UserDto {
@AutoMap()
firstName: string;
@AutoMap()
lastName: string;
@AutoMap()
fullName: string;
@AutoMap()
username: string;
@AutoMap(() => BioDto)
bio: BioDto;
}
export class BioDto {
@AutoMap()
jobTitle: string;
@AutoMap()
jobSalary: number;
@AutoMap()
birthday: string;
@AutoMap()
avatarUrl: string;
}
In addition to attaching @AutoMap() on most properties of both User and UserDto, we also remove all the existing mapping logics in UserDto. The result is UserDto no longer needs to be aware of User.
@AutoMap() can help AutoMapper to track the property and its type. For nested model like Bio, we help @AutoMap() by providing a function that returns the type (e.g.: () => Bio)
info
Read more about @AutoMap()
tip
If you want to remove the verbosity with @AutoMap(), check out Transformer Plugin