Search code examples
typescriptclass-transformer

plainToInstance cannot convert complex sub-properties


I want to convert an Entity into a DTO object. Entities contain extra properties compared to the corresponding DTO type, which I don't want exposed.

The difficulty is that both objects contains properties that are also entities and DTOs.

It seems that plainToInstance struggles with sub-properties conversion.

Here is the used code to convert:

plainToInstance(DtoA, entityObjectA, { excludeExtraneousValues: true, exposeUnsetFields: false, enableImplicitConversion: true })

excludeExtraneousValues set to true to avoid exposing information. exposeUnsetFields set to false to avoid polluting the DTO object. enableImplicitConversion set to true to try to convert sub-entities into sub-DTO objects.

It seems that the implicit conversion does not do what I expect.

Example of the issue:


export class DtoA {
    public dtos: DtoB[];
}

export class DtoB {
    public dtos: DtoC[];
}

export class DtoC {
    // some properties
}

On entity side, properties are named the same, but of course, properties are entities, not DTOs.

When using plainToInstance, like above, on EntityA, I get:

{
    dtos: [{}, {}, {}]
}

Where sub-entities are not converted to DTO objects.

If I pass JSON.stringify(entityObjectA) to plainToInstance instead of entityObjectA, I get a a string, where all quotes are escaped, instead of an object DtoA:

"{\"dtos\":[{\"dtos\": ...}]}"

More information:

  • These entities & DTO objects are declared in an external typescript library
  • All DTO objects' properties have the @expose() decorator
  • class-transformer version ^0.5.1 in both the project running plainToInstance and in the library

What am I missing?

Thank you


Solution

  • I've found the issue. To use plainToClass or plainToInstance with the option excludeExtraneousValues, you need to set:

    • @Expose() on all properties to set, and on the class itself, in the out class (dto classes in my question)
    • enableImplicitConversion to true
    • @Type(() => ObjectType) for arrays, in the example, an array containing ObjectType objects, ex: public arrayOfObjects: ObjectType[];