Ответ
Да, если DTO (Data Transfer Object) имеют полностью идентичную структуру и семантику, я выношу их в общий базовый класс или интерфейс. Это следует принципу DRY (Don't Repeat Yourself) и упрощает поддержку.
Пример на TypeScript для Node.js/Express:
// 1. Общий базовый интерфейс
interface BaseUserDto {
email: string;
firstName: string;
lastName: string;
}
// 2. Специфичные DTO наследуют или расширяют базовый
interface UserCreateDto extends BaseUserDto {
password: string; // Дополнительное поле только для создания
}
interface UserUpdateDto extends BaseUserDto {
// Пока полей нет, но структура общая
}
interface UserResponseDto extends BaseUserDto {
id: string;
createdAt: Date;
}
// 3. Использование в контроллере Express
app.post('/users', (req: Request<{}, {}, UserCreateDto>, res: Response) => {
// Валидация и обработка req.body
});
app.patch('/users/:id', (req: Request<{ id: string }, {}, UserUpdateDto>, res: Response) => {
// Обновление пользователя
});
Когда НЕ стоит объединять:
- Если DTO могут эволюционировать по-разному (например, в
UserUpdateDtoполеemailстанет опциональным, а вUserCreateDto— обязательным). - Если они используются в разных bounded context'ах (доменная модель разная). В таких случаях дублирование может быть менее вредным, чем неправильная абстракция.