# Subtyping

Let's take a source base type `Entity`, two its subtypes (`FooEntity`, `BarEntity`), for a destination take a base class `Dto` and two its subtypes (`FooDto`, `BarDto`). To create mapping that handles this polymorphic scenario, define a discriminator and register subtype mappings to the supertype via `mapSubtype`.

```typescript
class Entity {
    readonly discriminator: string;
    createdAt: string;
    property: string;
}

class FooEntity extends Entity {
    readonly discriminator = 'Foo';
}

class BarEntity extends Entity {
    readonly discriminator = 'Bar';
}

class Dto {
    property: string;
    createdAt: string;
}

class FooDto extends Dto {
    fooProperty: number;
}

class BarDto extends Dto {
    barProperty: number;
}
```

Setup mapping pairs for types above.

```typescript
const EntityToDto = new MappingPair(Entity, Dto);

// "private" concrete mapping pairs
const FooEntityToDto = new MappingPair(FooEntity, FooDto);
const BarEntityToDto = new MappingPair(BarEntity, BarDto);
```

Register subtypes to the base type map via `mapSubtype`. Subtype map automatically inherits from its base so there is no need to explicitly define base/subtypes via `includeBase` or `include`.

For the discriminator we simply use read only property `discriminator` that is defined on both source subtypes. We can also exclude this property from mapping to the destination object.

```typescript
const mapper = new MapperConfiguration(cfg => {
    cfg.createAutoMap(EntityToDto, {
        createdAt: opt => opt.mapFrom(src => '3020-01-01'),
    })
        .forSourceMember('discriminator', opt => opt.ignore())
        .mapSubtype(FooEntityToDto, src => src.discriminator === 'Foo')
        .mapSubtype(BarEntityToDto, src => src.discriminator === 'Bar');

    cfg.createAutoMap(FooEntityToDto, {
        fooProperty: opt => opt.mapFrom(src => parseInt(src.property))
    });

    cfg.createAutoMap(BarEntityToDto, {
        barProperty: opt => opt.mapFrom(src => parseInt(src.property))
    });
}).createMapper();
```

Perform mapping against the base mapping token `EntityToDto`.

```typescript
const fooSource = new FooEntity();
fooSource.property = '123';
fooSource.createdAt = '2020-01-01';

const foo = mapper.map(EntityToDto, fooSource) as FooDto;
// "foo" is instance of "FooDto" and have following properties:
// {
//     property: '123',
//     fooProperty: 123,
//     createdAt: '3020-01-01'
// }

const barSource = new BarEntity();
barSource.property = '123';
barSource.createdAt = '2020-01-01';

const bar = mapper.map(EntityToDto, barSource) as BarDto;
// "bar" is instance of "BarDto" and have following properties:
// {
//     property: '123',
//     barProperty: 123,
//     createdAt: '3020-01-01'
// }
```
