Platform
    • RTK Query
    • Mock Server (MSW)
    • Data Converters
Projects
  • API Connections & Tools
  1. Documentation
  2. Data Converters

Backend and Frontend Converters (Mappers)

Guide on decoupling API contracts and internal application data models using mappings (DTO -> Domain Model).

Data Mapping Architecture

Benefits: Converters isolate the UI from backend changes, allow data formatting (dates, enums), and guarantee layer-level type safety.

Entity Converters File Structure

Naming Conventions

  • Converters:

    Located in the converters/ folder. Files are named following the [entity-name].converters.ts pattern. They use types from the sibling folder for data transformation.

  • Types and Interfaces:

    Located in the types folder. Must be divided into *.backend.interface.ts (raw DTOs) and *.interface.ts (UI models). All types are exported via index.ts.

01Mapping to Frontend (Domain Model)

Transforming raw backend data (snake_case, strings instead of dates) into camelCase and typed objects for the UI. mapToFrontend is the most critical stage.

converters/booking-order.converters.ts
1import { formatDate } from "@/shared/lib/utils"; 2import { type IEntityBackend, type IEntity } from "../types"; 3 4export const mapEntityToFrontend = ( 5 data: IEntityBackend 6): IEntity => ({ 7 id: data.id, 8 fullName: data.full_name, 9 dateCreated: formatDate(data.created_at), 10 status: data.status_code 11});

02Mapping to Backend (DTO)

Preparing data before sending. Used when creating or updating entities to return to the DTO format expected by the API.

converters/booking-order.converters.ts
1import { 2 type IEntityBackend, 3 type IEntity 4} from "../types"; 5 6export const mapEntityToBackend = ( 7 data: Partial<IEntity> 8): Partial<IEntityBackend> => ({ 9 id: data.id, 10 full_name: data.fullName, 11 created_at: data.dateCreated, 12 status_code: data.status 13});

03Filter Conversion

A special case of mapping search filter state into query parameters. Allows convenient array joining, handling empty values, and API-specific formats.

converters/booking-order.converters.ts
1import { type IEntityFilters } from "../types"; 2 3export const mapEntityFiltersToBackend = ( 4 filters: IEntityFilters 5) => ({ 6 page: filters.page, 7 limit: filters.limit, 8 search: filters.search || undefined, 9 status: filters.status.length > 0 10 ? filters.status.join(",") 11 : undefined 12});

04RTK Query Integration

Converters are injected directly into endpoint definitions: transformResponse for data retrieval and query (params/body) for data submission.

api/[entity-name].service.ts
1import { authApi } from "@/entities/auth/api/auth.api"; 2import { 3 mapEntityFiltersToBackend, 4 mapEntityPaginatedToFrontend, 5 mapEntityToBackend 6} from "../converters"; 7 8export const entityApi = authApi.injectEndpoints({ 9 endpoints: (builder) => ({ 10 getEntities: builder.query<TResponse, TFilters>({ 11 query: (filters) => ({ 12 url: "/entity/list", 13 params: mapEntityFiltersToBackend(filters) 14 }), 15 transformResponse: (response: TResponseBackend) => 16 mapEntityPaginatedToFrontend(response) 17 }), 18 updateEntity: builder.mutation<void, TEntity>({ 19 query: (body) => ({ 20 url: "/entity/update", 21 method: "POST", 22 body: mapEntityToBackend(body) 23 }) 24 }) 25 }) 26});