Skip to content
AutoMapper TypeScript
Esc
navigateopen⌘Jpreview
On this page

POJOs strategy

Register explicit metadata for interfaces, type aliases, and plain JavaScript objects.

TypeScript interfaces do not exist at runtime. @automapper/pojos associates their property metadata with string or symbol identifiers.

npm install @automapper/core @automapper/pojos
pnpm add @automapper/core @automapper/pojos
bun add @automapper/core @automapper/pojos

Register metadata

Metadata must be registered before createMap():

interface User {
  firstName: string;
  lastName: string;
}

interface UserDto {
  firstName: string;
  lastName: string;
  fullName: string;
}

PojosMetadataMap.create<User>('User', {
  firstName: String,
  lastName: String,
});

PojosMetadataMap.create<UserDto>('UserDto', {
  firstName: String,
  lastName: String,
  fullName: String,
});

const mapper = createMapper({ strategyInitializer: pojos() });

createMap<User, UserDto>(
  mapper,
  'User',
  'UserDto',
  forMember(
    (destination) => destination.fullName,
    mapFrom((source) => `${source.firstName} ${source.lastName}`),
  ),
);

const dto = mapper.map<User, UserDto>(user, 'User', 'UserDto');

The generic on PojosMetadataMap.create<User>() checks metadata keys against the interface.

Nested and array metadata

Register nested identifiers before their parent:

PojosMetadataMap.create<Address>('Address', {
  street: String,
});

PojosMetadataMap.create<User>('User', {
  name: String,
  address: 'Address',
  previousAddresses: ['Address'],
  logins: [Date],
});

String identifiers are normalized to global symbols internally. You may provide symbols directly when global string identity is undesirable.

Circular depth

PojosMetadataMap.create<User>('User', {
  organization: { type: 'Organization', depth: 2 },
});

The default depth is 1.

Reset metadata

PojosMetadataMap is process-wide. Reset it when tests need isolated metadata registration:

afterEach(() => PojosMetadataMap.reset());

Last updated on July 16, 2026

Was this page helpful?