Информационные системы предназначены для обработки данных, а DTO (Data Transfer Object) является важным концептом в современной разработке. В “классическом” понимании DTO являются простыми объектами (без логики), описывающими структуры данных, передаваемых “по проводам” между разнесенными процессами (remote processes). Зачастую данные "по проводам" передаются в виде JSON. Если DTO используются для передачи данных между слоями приложения (база данных, бизнес-логика, представления),  то, по Фаулеру, это называется LocalDTO. Некоторые разработчики (включая самого Фаулера) негативно относятся к локальным DTO. Основным отрицательным моментом локального применения DTO является необходимость маппинга данных из одной структуры в другую при их передаче от одного слоя приложения к другому. Тем не менее, DTO являются важным классом объектов в приложениях и в этой статье я покажу JS-код, который на данный момент считаю оптимальным для DTO (в рамках стандартов ECMAScript 2015+). Во-первых, в коде должна быть отражена сама структура данных. Лучше всего это делать с использованием классов (аннотации JSDoc помогают ориентироваться в типах данных): Это пример простой структуры данных, где каждый атрибут является примитивом. Если некоторые атрибуты сами являются структурами, то класс выглядит примерно так: Как правило, создание экземпляра DTO в половине случаев связано разбором имеющейся структуры данных, полученной "по проводам" с "другой стороны". Поэтому конструктор DTO получает на вход некоторый JS-объект, из которого пытается извлечь знакомые ему данные: В конструкторе структуры со сложными атрибутами используются конструкторы для соответствующих атрибутов: Если какой-то атрибут представляет из себя массив, то в конструкторе его разбор выглядит примерно так: Если какие-то данные должны быть сохранены в атрибуте без разбора, то это тоже возможно (хотя к DTO имеет такое себе отношение): Метаданные - это информация о коде. Метаданные позволяют отследить, где используются соответствующие атрибуты объекта: Например, при выборке данных из БД: Результирующую выборку можно напрямую передавать в конструктор SaleOrder, а затем получившийся DTO выкидывать на web в качестве ответа. Если сводить воедино все три составляющих DTO (структура, конструктор, метаданные), то получается примерно такой es-модуль: Подобный подход позволяет извлекать знакомые подструктуры данных из больших структур (конфигурационных файлов, ответов от сервисов и т.п.), непосредственно относящиеся к текущему контексту, а IDE, за счёт аннотаций, имеет возможность помогать разработчику ориентироваться в этой подструктуре. "Вот и всё, что я могу сказать об этом." (с) Коллега @chemaxa отметил в комменте, что "есть же уже давно https://github.com/OAI/OpenAPI-Specification ... и есть куча генераторов кода под разные языки для dto разной степени паршивости которые выдают код описанный в статье." Я попробовал использовать генератор для "javascript" (на выходе код ES2015+), получил вот это (убрал только пустые строки): Что привлекло внимание. Во-первых, двухступенчатое создание объекта: Полагаю, что вынос инициализирующего кода из конструктора в статический метод минимизирует потребление памяти в runtime - статические методы share'ятся между всеми экземплярами класса, а не "навешиваются" на каждый экземпляр. Во-вторых, значения по-умолчанию вешаются на прототип, используемый для создания экземпляров класса: Это опять-таки направлено на минимизацию потребления памяти при массовом создании экземпляров. В третьих, отсутствуют метаданные об используемых в DTO атрибутах: Наверное, с точки зрения разрабов этого генератора кода такая информация показалась им излишней и при необходимости её вполне можно добавить в генератор. В общем, на мой взгляд, вполне неплохое совпадение изложенного в моей публикации (структура, конструктор, метаданные) с практикой (структура, конструктор). Что касается статических методов, то Safary только 26-го апреля этого года научилась понимать статику (хотя того же эффекта можно добиться за счёт прямого переноса методов в класс: ConfigEmail.initialize = function(obj){}). Хочу отметить, что я не считаю, что DTO уместны только лишь в разрыве "браузер" - "сервер". IMHO, везде, где данные можно представить в виде JSON'а, для его разбора и структуризации пригодна вот такая структура. В том числе и для выборки данных из хранилищ, и для загрузки конфигурационных параметров приложения из файлов. Тянуть во все эти случаи OpenAPI-генератор мне представляется сомнительным. Коллега @nin-jin в своём комментарии справедливо заметил, что хорошо бы "проверять типы полей перед их сохранением". Я могу согласиться, что было бы правильным приводить типы данных к ожидаемым (нормализовать данные). Кстати, так и делается в OpenAPI-генераторе: Хотя синтаксис его собственной платформы $mol, кажется мне более "прозрачным": Насколько я понял, функция Rec предназначена для создания простых дата-объектов (объекты без логики, только с данными) "на лету". В общем-то это и есть DTO, только режима runtime, а не уровня кода (те же метаданные в моём примере позволяют программисту "метить" места использования соотв. DTO и находить их без запуска приложения). Что касается его ремарки "делать все поля опциональными - сомнительное решение", то в данной публикации я рассматривал DTO прежде всего как фильтр, структурирующий JSON данные - на вход подаётся некоторый объект, а фильтр извлекает из него (или его части) знакомую ему структуру. Это не валидатор, поэтому - норм. Валидатор уже потом может брать готовую структуру, пробегать по ней и принимать решения, что делать, если чего-то для чего-то не хватает. Коллеге @DmitryKoterov просто спасибо за заботу о моём душевном здоровье, но воспользоваться его советом перейти на TypeScript я не смогу - мешает старая психологическая травма, полученная лет 10-15 назад, когда я пытался понять, почему GWT-приложение в production mode работает иначе, чем в dev, и видел совсем не тот код, который создавал я и мои коллеги. Мы писали на прекрасной Java, а там был обфусцированный и минифицированный JavaScript. Меня так это контузило, что я потом очень долго писал на PHP. Вот только пару лет назад слегка попустило. Этот абзац я вставил в начало публикации специально для того, чтобы при сохранении он перенесся в конец текста, а второй абзац стал первым. Вот такая занимательная бага есть сегодня на Хабре. wiredgeese.com