diff --git a/README.md b/README.md index d9e1c1230..57c931948 100644 --- a/README.md +++ b/README.md @@ -716,6 +716,62 @@ export class Photo { } ``` +### Array with multiple types[⬆](#table-of-contents) + +You can also use array with multiple types, using the `@Transform()` decorator. + +```typescript +class Photo { + type: string; + filename: string; +} + +class Landscape extends Photo { + local: string; +} + +class Portrait extends Photo { + person: string; + gender: string; +} + +export class Album { + @Transform(({ value }) => { + return value.map(item => { + const options = { + portrait: Portrait, + landscape: Landscape, + }; + const obj = options[item.type]; + return plainToInstance(obj, item); + }); + }) + photos: Array; +} +``` + +Is very util to add type for object arrays with dynamic types. + +```typescript +const albumJson = { + photos: [ + { + type: 'landscape', + filename: 'cataratas.png', + local: 'Cataratas do Iguaçu - PR/BR', + }, + { + type: 'portrait', + filename: 'topmodel.jpg', + person: 'Alessandra Ambrósio', + gender: 'female', + }, + ], +}; + +const albumObject = plainToInstance(Album, albumJson); +``` + Library will handle proper transformation automatically. ES6 collections `Set` and `Map` also require the `@Type` decorator: diff --git a/sample/sample6-multiple-type-array/Album.ts b/sample/sample6-multiple-type-array/Album.ts new file mode 100644 index 000000000..7b569f448 --- /dev/null +++ b/sample/sample6-multiple-type-array/Album.ts @@ -0,0 +1,43 @@ +import { Transform, plainToInstance } from '../../src'; + +class Photo { + type: string; + filename: string; +} + +class Portrait extends Photo { + person: string; + gender: string; +} + +class Sports extends Photo { + sport: string; + origin: string; +} + +export class Landscape extends Photo { + local: string; + + getLocation(): string { + return `The location of this picture is ${this.local.split('-')[1].trim()}`; + } +} + +export class Album { + @Transform(({ value }) => { + return value.map(item => { + const options = { + portrait: Portrait, + sports: Sports, + landscape: Landscape, + }; + const obj = options[item.type]; + return plainToInstance(obj, item); + }); + }) + photos: Array; + + findByType(type: string): T { + return this.photos.find(item => item.type === type) as T; + } +} diff --git a/sample/sample6-multiple-type-array/app.ts b/sample/sample6-multiple-type-array/app.ts new file mode 100644 index 000000000..1105d5f8f --- /dev/null +++ b/sample/sample6-multiple-type-array/app.ts @@ -0,0 +1,30 @@ +import { plainToInstance } from '../../src'; +import { Album, Landscape } from './Album'; + +const albumJson = { + photos: [ + { + type: 'landscape', + filename: 'cataratas.png', + local: 'Cataratas do Iguaçu - PR/BR', + }, + { + type: 'portrait', + filename: 'topmodel.jpg', + person: 'Alessandra Ambrósio', + gender: 'female', + }, + { + type: 'sports', + filename: 'ferrari.png', + sport: 'F1', + origin: 'The United Kingdom', + }, + ], +}; + +const albumObject = plainToInstance(Album, albumJson); +console.log(albumObject); + +const landscape = albumObject.findByType('landscape'); +console.log(landscape.getLocation());