Careeroza
Mapped Types
PartialType, PickType, OmitType, IntersectionType
Update DTOs usually have the same fields as create DTOs, but all optional. Instead of copying the class, use mapped types. They copy the validation decorators too.
Example
npm i @nestjs/mapped-typesExample output
added 1 package in 2s
src/products/dto/update-product.dto.ts
import { OmitType, PartialType, PickType, IntersectionType } from '@nestjs/mapped-types';
import { CreateProductDto } from './create-product.dto';
export class UpdateProductDto extends PartialType(CreateProductDto) {} // all fields optional
export class UpdateStockDto extends PickType(CreateProductDto, ['stock'] as const) {} // only stock
export class PublicProductDto extends OmitType(CreateProductDto, ['description'] as const) {}
class AuditDto { updatedBy: string; }
export class AdminUpdateProductDto extends IntersectionType(UpdateProductDto, AuditDto) {}Note: If you use Swagger, import these helpers from @nestjs/swagger instead, so the API docs also know about the fields.
The Same Idea in TypeScript Types
Example
Mapped types are named after TypeScript utility types. The difference: TS utility types exist only at compile time, NestJS mapped types also create a real class with the validation rules.
interface CreateProduct {
name: string;
description?: string;
price: number;
stock: number;
category: string;
}
type UpdateProduct = Partial<CreateProduct>;
type UpdateStock = Pick<CreateProduct, 'stock'>;
type PublicProduct = Omit<CreateProduct, 'description'>;
const patch: UpdateProduct = { price: 1199 };
const stock: UpdateStock = { stock: 50 };
const card: PublicProduct = { name: 'JBL Go 3', price: 2999, stock: 12, category: 'audio' };
console.log(patch, stock, card);Output
{ price: 1199 } { stock: 50 } { name: 'JBL Go 3', price: 2999, stock: 12, category: 'audio' }