> For the complete documentation index, see [llms.txt](https://dynamic-mapper.gitbook.io/dynamic-mapper/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dynamic-mapper.gitbook.io/dynamic-mapper/configuration/subtyping.md).

# 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'
// }
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dynamic-mapper.gitbook.io/dynamic-mapper/configuration/subtyping.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
