Skip to content
AutoMapper TypeScript
Esc
navigateopen⌘Jpreview
On this page

Overview

What AutoMapper TypeScript is, the problems it solves, and when conventions are a good fit.

What AutoMapper does

AutoMapper maps one object shape to another by convention. When source and destination models use matching property names and compatible metadata, the mapper can copy values without per-property configuration.

Use mapping configuration only for the differences: computed values, renamed members, conversions, conditions, or nested types that cannot be inferred.

When it fits

AutoMapper is most useful when:

  • destination types are mostly subsets or projections of source types;
  • property names follow consistent conventions;
  • you repeatedly map domain, persistence, API, or view models;
  • central mapping profiles are easier to maintain than scattered constructors and object literals.

If most destination members need custom business logic, explicit transformation code is usually clearer.

How it is structured

Every mapper combines @automapper/core with one mapping strategy:

Strategy Use it for
classes() TypeScript classes with @AutoMap() metadata
pojos() Interfaces, types, and plain objects with explicit metadata
mikro() MikroORM entities; extends the classes strategy
sequelize() Sequelize models; extends the classes strategy

The @automapper/nestjs package integrates a mapper with NestJS dependency injection, profiles, interceptors, and pipes.

The basic flow

import { classes } from "@automapper/classes";
import { createMap, createMapper } from "@automapper/core";

const mapper = createMapper({ strategyInitializer: classes() });

createMap(mapper, User, UserDto);

const dto = mapper.map(user, User, UserDto);

Types follow the destination

The destination identifier drives the result type across single, array, and asynchronous mapping. These types come from the TypeScript compiler; hover an identifier to inspect it in place.

createMap<User, UserDto>(mapper: Mapper, source: ModelIdentifier<User>, destination: ModelIdentifier<UserDto>, ...mappingConfigFns: (MappingConfiguration<User, UserDto> | undefined)[]): Mapping<User, UserDto> (+1 overload)createMap(const mapper: Mappermapper, class UserUser, class UserDtoUserDto);

const 
const dto: UserDto
dto
= const mapper: Mappermapper.Mapper.map<User, UserDto>(sourceObject: User, sourceIdentifier: ModelIdentifier<User>, destinationIdentifier: ModelIdentifier<UserDto>, options?: MapOptions<User, UserDto, Record<string, unknown>> | undefined): UserDto (+1 overload)map(const user: Useruser, class UserUser, class UserDtoUserDto);
const
const dtos: UserDto[]
dtos
= const mapper: Mappermapper.Mapper.mapArray<User, UserDto>(sourceArray: User[], sourceIdentifier: ModelIdentifier<User>, destinationIdentifier: ModelIdentifier<UserDto>, options?: MapOptions<User[], UserDto[], Record<string, unknown>> | undefined): UserDto[] (+1 overload)mapArray(const users: User[]users, class UserUser, class UserDtoUserDto);
const
const pending: Promise<UserDto>
pending
= const mapper: Mappermapper.Mapper.mapAsync<User, UserDto>(sourceObject: User, sourceIdentifier: ModelIdentifier<User>, destinationIdentifier: ModelIdentifier<UserDto>, options?: MapOptions<User, UserDto, Record<string, unknown>> | undefined): Promise<UserDto> (+1 overload)
Maps `sourceObject` and resolves with the result.
@remarksMember mapping itself is synchronous, but any `beforeMap`/`afterMap` callbacks that return a promise are collected and awaited before the returned promise resolves. Use the synchronous {@link map} when no async callbacks are involved.
mapAsync
(const user: Useruser, class UserUser, class UserDtoUserDto);

Continue with Installation, or follow the tutorial for a complete example.

Last updated on July 16, 2026

Was this page helpful?