AutoMapper TypeScript
website·Indexed 30 days ago
https://automapperts.netlify.app/A convention-based object-to-object mapper for TypeScript. It handles matching properties, nested models, and flattening with support for classes, POJOs, ORMs, and integration with NestJS 10 and 11.
What's inside AutoMapper TypeScript
- AutoMapper TypeScript is a library providing convention-based object mapping for TypeScript. It is designed to handle mapping across various data structures, including classes, Plain Old JavaScript Objects (POJOs), Object-Relational Mappers (ORMs), and is compatible with NestJS.
Overview of AutoMapper TypeScript
AutoMapper TypeScript is an object-to-object mapper designed to handle matching properties, nested models, and flattening. It allows developers to focus mapping code on actual transformations rather than repetitive property assignments.Handle mapping failures with MapMemberError
TheMapMemberErrorclass is thrown by@automapper/corewhen the mapping of a single member fails. It extendsAutoMapperErrorand serves as a wrapper around the original error that caused the failure, providing additional context about which member and destination were involved.// Example of how MapMemberError is structured // new MapMemberError(memberPath, destinationName, originalError)Understand AutoMapper's core functionality and use cases
AutoMapper maps one object shape to another by convention. When source and destination models have matching property names and compatible metadata, values are copied automatically without per-property configuration. Configuration is only required for differences such as computed values, renamed members, conversions, conditions, or nested types.
AutoMapper is best suited for scenarios where:
- Destination types are subsets or projections of source types.
- Property names follow consistent conventions.
- There is a need to repeatedly map between domain, persistence, API, or view models.
- Central mapping profiles are preferred over scattered constructors and object literals.
Ignore a property from automatic metadata generation
The transformer plugin automatically generates metadata for matching model properties unless they are already decorated with@AutoMap(). To explicitly prevent a property from having generated metadata, add the/** @autoMapIgnore */JSDoc comment above the property.class UserDto { firstName!: string; /** @autoMapIgnore */ internalState!: string; }Install @automapper/pojos
To use the POJOs strategy for mapping TypeScript interfaces, install both the core library and the pojos strategy package.npm install @automapper/core @automapper/pojosExtend a base mapping to derived models
Use theextend()function to inherit mapping configurations from a base entity/DTO pair to a more specific one. This is intended for structurally related models. Explicit member configurations defined on the new mapping take precedence and will not be overwritten by the inherited configuration from the base mapping.// 1. Create the base mapping const baseMapping = createMap(mapper, BaseEntity, BaseDto); // 2. Extend the base mapping for a specific entity createMap( mapper, User, UserDto, extend(baseMapping), forMember( (destination) => destination.name, mapFrom((source) => source.displayName), ), ); // Alternative: Extend using the entity/DTO types directly createMap(mapper, Admin, AdminDto, extend(BaseEntity, BaseDto));Use asynchronous resolvers with mapAsync
In version 9, selectors and resolvers (including those created withmapWithArguments) can return promises. To resolve these asynchronous values, usemapAsync()ormapArrayAsync()instead of the standardmap()method.const dto = await mapper.mapAsync(item, Item, ItemDto, { extraArgs: () => ({ region: 'us-east' }), });Handle circular models in class mappings
Nested metadata defaults to a traversal depth of1. To handle circular relationships that require deeper traversal, use the options object within@AutoMap()to specify a higherdepthvalue. Ensure the depth is bounded to prevent infinite loops in circular graphs.class User { @AutoMap({ type: () => Organization, depth: 2 }) organization!: Organization; }Use forSelf() to map nested objects without auto-flattening prefixes
In AutoMapper, auto-flattening typically maps a nested property like
item.nameto a destination property nameditemName. Use theforSelf()function when the destination object intentionally omits this prefix and you want to map the properties of a nested source object directly onto the destination object.forSelf()works by creating or reusing mapping information from the nested source model to the destination, then selecting the nested source value at runtime.class CartItemDto { @AutoMap() name!: string; @AutoMap() price!: number; @AutoMap() quantity!: number; } createMap( mapper, CartItem, CartItemDto, forSelf(Item, (source) => source.item), );Use asynchronous callbacks with mapAsync
When using themapAsyncAPI,beforeMapcallbacks can be defined asasyncfunctions to perform asynchronous pre-processing (e.g., hydrating data from a database) before the mapping occurs.createMap( mapper, User, UserDto, beforeMap(async (source) => hydrateUser(source)), ); const dto = await mapper.mapAsync(user, User, UserDto);Use asynchronous mapping and lifecycle callbacks in AutoMapper 9
v9-0-0AutoMapper 9 introduces genuine asynchronous mapping. Async map and mutation APIs now await promise-returning member resolvers and lifecycle callbacks. For NestJS users, theMapInterceptorandMapPipenow await asynchronous object and array mappings.