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.

Tokens
40K
Snippets
267
Records
331
Agent score
75%

What's inside AutoMapper TypeScript

  1. Overview of 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.
  2. 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.
  3. Handle mapping failures with MapMemberError

    The MapMemberError class is thrown by @automapper/core when the mapping of a single member fails. It extends AutoMapperError and 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)
  4. 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.
  5. 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;
    }
  6. 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/pojos
  7. Extend a base mapping to derived models

    Use the extend() 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));
  8. Use asynchronous resolvers with mapAsync

    In version 9, selectors and resolvers (including those created with mapWithArguments) can return promises. To resolve these asynchronous values, use mapAsync() or mapArrayAsync() instead of the standard map() method.
    const dto = await mapper.mapAsync(item, Item, ItemDto, {
      extraArgs: () => ({ region: 'us-east' }),
    });
  9. Handle circular models in class mappings

    Nested metadata defaults to a traversal depth of 1. To handle circular relationships that require deeper traversal, use the options object within @AutoMap() to specify a higher depth value. Ensure the depth is bounded to prevent infinite loops in circular graphs.
    class User {
      @AutoMap({ type: () => Organization, depth: 2 })
      organization!: Organization;
    }
  10. Use forSelf() to map nested objects without auto-flattening prefixes

    In AutoMapper, auto-flattening typically maps a nested property like item.name to a destination property named itemName. Use the forSelf() 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),
    );
  11. Use asynchronous callbacks with mapAsync

    When using the mapAsync API, beforeMap callbacks can be defined as async functions 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);
  12. Use asynchronous mapping and lifecycle callbacks in AutoMapper 9

    v9-0-0
    AutoMapper 9 introduces genuine asynchronous mapping. Async map and mutation APIs now await promise-returning member resolvers and lifecycle callbacks. For NestJS users, the MapInterceptor and MapPipe now await asynchronous object and array mappings.