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/classes
for this tutorial. Check Installation for more details. - The rest of the tutorial will apply to
@automapper/classes
only. 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