Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easy Map for properties with the same name. #582

Open
TA50 opened this issue Oct 18, 2023 · 2 comments
Open

Easy Map for properties with the same name. #582

TA50 opened this issue Oct 18, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@TA50
Copy link

TA50 commented Oct 18, 2023

Is your feature request related to a problem? Please describe.

No response

Describe the solution you'd like

Problem

Let's assume we have the following classes:

class UserDto {
    id: number;
    email: string;
    name: string;
}

class User {
    id: number;
    email: string;
    name: string;
    password: string;
}

And we would like to create a simple mapping from User to UserDto. As often we will use a lot of properties with the same name in the entity and the dto. For now, the solution is:

createMap(mapper,
    User,
    UserDto,
    forMember(d => d.name, mapFrom(s => s.name)),
    forMember(d => d.email, mapFrom(s => s.email)),
    forMember(d => d.id, mapFrom(s => s.id)),
    // As you can see, the password is not mapped
);

Mapping properties between classes, such as User and UserDto, in JavaScript is currently a manual and tedious process. It involves repetitive work, especially when dealing with numerous properties, and can become challenging when new properties are added. Unlike AutoMapper in C#, which automatically maps properties with the same names, JavaScript lacks this capability due to the inability to extract property names from classes.

The primary problem is to simplify and automate property mapping in JavaScript, similar to AutoMapper in C#, by automatically mapping properties with matching names unless explicitly ignored.

Solution

To streamline the configuration and enable the automatic mapping of properties with matching names, I suggest the implementation of shortcut functions. These functions serve as efficient ways to configure the mapping process manually.

copySingleProperty function:

createMap(mapper,
    User,
    UserDto,
    copySingleProperty("id"),
    copySingleProperty("name"),
    copySingleProperty("email"),
);

copyManyProperties function:

createMap(mapper,
    User,
    UserDto,
    copyManyProperties('id', 'name', 'email'),
    // As you can see, the password is not mapped
);

This approach offers a more concise and manageable method for mapping properties. Although achieving automatic mapping identical to AutoMapper in C# may not be feasible in JavaScript due to the inability to extract property names from classes, these functions significantly enhance the mapping process and reduce repetitive tasks.

By employing this technique, developers have the flexibility to add properties as a list. This list can be created either manually or by utilizing a proxy object to retrieve the property names.

Here's a basic example of code for the copySingleProperty function:

function copySingleProperty<TSource, TDestination>(
    propertyName: string & keyof TSource & keyof TDestination,
): MappingConfiguration<TSource, TDestination> {
    return (mapping) => {
        const memberPath = [propertyName];
        const mappingProperty: MappingProperty<TSource, TDestination> = [
            memberPath,
            [mapFrom((source: TSource) => source[propertyName])],
        ];
        mapping[MappingClassId.customProperties].push([
            memberPath,
            mappingProperty,
            undefined,
        ]);
    };
}

Furthermore, consider making utility functions available for developers to simplify the creation of their custom configurations. These utilities, such as getMember, getMemberPath, and others, can facilitate the process of defining individualized mapping configurations.

Describe alternatives you've considered

No response

Additional context

Dependencies:

  • @automapper/classes (Version 8.7.7)
  • @automapper/core (Version 8.7.7)
  • typescript (Version 5.2.2)
  • tsc (Version 2.0.4)
@TA50 TA50 added the enhancement New feature or request label Oct 18, 2023
@love-it-jannik
Copy link

This is exactly what I use the @AutoMap() Decorator in @automapper/classes for.

class UserDto {
    @AutoMap()
    id: number;

    @AutoMap()
    email: string;

    @AutoMap()
    name: string;
}

class User {
    @AutoMap()
    id: number;

    @AutoMap()
    email: string;

    @AutoMap()
    name: string;

    password: string;
}

For creating the mapping I simply need

createMap(
    mapper,
    User,
    UserDto,
);

No need for any additional mapping information and password is not mapped, as it does not have an @AutoMap() Decorator.

Hope this helps.

@agzr
Copy link

agzr commented Jan 29, 2024

In version 8.8.0 you can also use the autoMap() function introduced by PR 588.

createMap(
    mapper,
    DecoratorlessUser,
    DecoratorlessUserDto,
    autoMap('firstName'),
    autoMap('lastName'),
    forMember(
        (d) => d.fullName,
        mapFrom((s) => s.firstName + ' ' + s.lastName)
    )
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants