class-transformer icon indicating copy to clipboard operation
class-transformer copied to clipboard

Adding @Alias decorator and allow multiple @Expose decorators

Open rgoupil opened this issue 2 years ago • 0 comments

Description

Thank you for this amazing library 🚀

It has been discussed several times (sometimes with some confusion): in some scenarios, being able to rename a property only when importing or exporting it can be useful.

For instance, I am reading rows from a file in a format A sent by a third party, then convert it to an object in my TS code. It might be logged or stored in a file in another format B later on. One of the field is named part_or_item_number in the format A, which is then converted to partRef in my JS object.

TLDR

plainToInstance should accept this object:

{
  "part_or_item_number": "part1234"
}

The property should be referenced as follow in the code:

findPart(myObj.partRef)

And instanceToPlain should then produce the following:

{
  "partRef": "part1234"
}

One would quickly suggest to use @Expose({ name: 'part_or_item_number' }), however it would also expose the property under the name part_or_item_number when using instanceToPlain.

Adding the option toClassOnly: true is not cutting it either as it would then hide the property when using instanceToPlain.

Another suggestion seen in one of the thread linked earlier is to use two @Expose:

...
  @Expose({ name: 'part_or_item_number', toClassOnly: true })
  @Expose({ toPlainOnly: true })
  partRef: string;
...

While it's a pretty neat idea, it simply doesn't work in the current state, as the last @Expose will always replace the previous ones.


This PR introduces two changes:

  • Allow the previous sample of code to work as described
  • Introduce an Alias decorator to reduce boilerplate in that scenario, using @Expose behind the scene to reduce duplication

The code above could be rewritten as the following with the same expected behaviour:

...
  @Alias({ from: 'part_or_item_number' })
  partRef: string;
...

There is also a slight rewriting of the map manipulation code in MetadataStorage.ts. I'm fine reverting it but it greatly improved the readability for me.

Checklist

  • [x] the pull request title describes what this PR does (not a vague title like Update index.md)
  • [x] the pull request targets the default branch of the repository (develop)
  • [x] the code follows the established code style of the repository
    • npm run prettier:check passes
    • npm run lint:check passes
  • [x] tests are added for the changes I made (if any source code was modified)
  • [x] documentation added or updated
  • [x] I have run the project locally and verified that there are no errors

Fixes

fixes #677, fixes #121, fixes #366

rgoupil avatar May 05 '22 17:05 rgoupil