☰ Mục lục series
Tài liệu NestJS tiếng Việt
  1. Nhập môn (Overview)
    1. Giới thiệu
    2. First steps
    3. Controllers
    4. Providers
    5. Modules
    6. Middleware
    7. Exception filters
    8. Pipes
    9. Guards
    10. Interceptors
    11. Custom decorators
  2. Nền tảng (Fundamentals)
    1. Custom providers
    2. Asynchronous providers
    3. Dynamic modules
    4. Injection scopes
    5. Circular dependency
    6. Module reference
    7. Lazy-loading modules
    8. Execution context
    9. Lifecycle events
    10. Discovery service
    11. Platform agnosticism
    12. Testing
  3. Kỹ thuật (Techniques)
    1. Configuration
    2. Database (SQL)
    3. MongoDB
    4. Validation
    5. Caching
    6. Serialization
    7. Versioning
    8. Task scheduling
    9. Queues
    10. Logging
    11. Cookies
    12. Events
    13. Compression
    14. File upload
    15. Streaming files
    16. HTTP module
    17. Session
    18. MVC
    19. Performance (Fastify)
    20. Server-Sent Events
  4. Bảo mật (Security)
    1. Authentication
    2. Authorization
    3. Encryption & Hashing
    4. Helmet
    5. CORS
    6. CSRF
    7. Rate limiting
    8. Vòng đời request
  5. OpenAPI (Swagger)
    1. Introduction
    2. Types and parameters
    3. Operations
    4. Security
    5. Mapped types
    6. Decorators
    7. CLI plugin
    8. Other features
  6. Recipes
    1. REPL
    2. CRUD generator
    3. SWC (fast compiler)
    4. Passport (auth)
    5. Hot reload
    6. MikroORM
    7. Router module
    8. Health checks (Terminus)
    9. CQRS
    10. Prisma
    11. Serve static
    12. Commander
    13. Async local storage
  7. WebSockets
    1. Gateways
    2. Exception filters
    3. Pipes
    4. Guards
    5. Interceptors
    6. Adapters
  8. Microservices
    1. Overview
    2. Redis
    3. MQTT
    4. NATS
    5. RabbitMQ
    6. Kafka
    7. gRPC
    8. Custom transporters
    9. Exception filters
    10. Pipes
    11. Pre-request hooks
    12. Guards
    13. Interceptors
  9. GraphQL
    1. Quick start
    2. Resolvers
    3. Mutations
    4. Subscriptions
    5. Scalars
    6. Directives
    7. Interfaces
    8. Unions and enums
    9. Field middleware
    10. Mapped types
    11. Plugins
    12. Complexity
    13. Extensions
    14. CLI plugin
    15. Generating SDL
    16. Sharing models
    17. Other features
    18. Federation
  10. CLI & triển khai
    1. CLI overview
    2. Workspaces
    3. Libraries
    4. Usage
    5. Scripts
    6. Deployment
    7. Standalone apps
  11. FAQ
    1. Serverless
    2. HTTP adapter
    3. Keep-Alive connections
    4. Global path prefix
    5. Raw body
    6. Hybrid application
    7. HTTPS & multiple servers
    8. Common errors
  12. Phụ lục
    1. Bảng thuật ngữ
OpenAPI (Swagger)

Mapped types (kiểu ánh xạ)

Bản dịch từ docs.nestjs.com/openapi/mapped-types

Khi xây dựng các tính năng như CRUD (Create/Read/Update/Delete), việc tạo ra các biến thể khác nhau từ một entity type gốc thường rất hữu ích. Nest cung cấp một số hàm tiện ích (utility function) thực hiện việc chuyển đổi type để công việc này thuận tiện hơn.

Partial

Khi xây dựng các type dùng để kiểm tra dữ liệu đầu vào (validation, còn gọi là DTO), việc tạo ra biến thể create và update từ cùng một type thường rất hữu ích. Ví dụ, biến thể create có thể yêu cầu tất cả các field, còn biến thể update có thể cho phép tất cả field là optional (tùy chọn).

Nest cung cấp hàm tiện ích PartialType() để giúp việc này dễ hơn và giảm thiểu code khung (boilerplate).

Hàm PartialType() trả về một type (class) có tất cả property của input type được đặt thành optional. Ví dụ, giả sử ta có một type create như sau:

import { ApiProperty } from '@nestjs/swagger';

export class CreateCatDto {
  @ApiProperty()
  name: string;

  @ApiProperty()
  age: number;

  @ApiProperty()
  breed: string;
}

Theo mặc định, tất cả các field này đều là bắt buộc. Để tạo một type có cùng các field nhưng mỗi field đều optional, hãy dùng PartialType() và truyền class reference (CreateCatDto) làm tham số:

export class UpdateCatDto extends PartialType(CreateCatDto) {}

Gợi ý Hàm PartialType() được import từ package @nestjs/swagger.

Pick

Hàm PickType() tạo ra một type (class) mới bằng cách chọn ra một tập property từ input type. Ví dụ, giả sử ta bắt đầu với một type như sau:

import { ApiProperty } from '@nestjs/swagger';

export class CreateCatDto {
  @ApiProperty()
  name: string;

  @ApiProperty()
  age: number;

  @ApiProperty()
  breed: string;
}

Ta có thể chọn ra một tập property từ class này bằng hàm tiện ích PickType():

export class UpdateCatAgeDto extends PickType(CreateCatDto, ['age'] as const) {}

Gợi ý Hàm PickType() được import từ package @nestjs/swagger.

Omit

Hàm OmitType() tạo ra một type bằng cách lấy tất cả property từ input type rồi loại bỏ một tập key cụ thể. Ví dụ, giả sử ta bắt đầu với một type như sau:

import { ApiProperty } from '@nestjs/swagger';

export class CreateCatDto {
  @ApiProperty()
  name: string;

  @ApiProperty()
  age: number;

  @ApiProperty()
  breed: string;
}

Ta có thể tạo ra một derived type có mọi property trừ name, như bên dưới. Trong cách viết này, tham số thứ hai truyền cho OmitType là một mảng tên property.

export class UpdateCatDto extends OmitType(CreateCatDto, ['name'] as const) {}

Gợi ý Hàm OmitType() được import từ package @nestjs/swagger.

Intersection

Hàm IntersectionType() kết hợp hai type thành một type (class) mới. Ví dụ, giả sử ta bắt đầu với hai type như sau:

import { ApiProperty } from '@nestjs/swagger';

export class CreateCatDto {
  @ApiProperty()
  name: string;

  @ApiProperty()
  breed: string;
}

export class AdditionalCatInfo {
  @ApiProperty()
  color: string;
}

Ta có thể tạo ra một type mới kết hợp tất cả property của cả hai type.

export class UpdateCatDto extends IntersectionType(
  CreateCatDto,
  AdditionalCatInfo,
) {}

Gợi ý Hàm IntersectionType() được import từ package @nestjs/swagger.

Composition (kết hợp nhiều utility)

Các hàm tiện ích mapped type này có thể kết hợp (compose) được với nhau. Ví dụ, đoạn code sau sẽ tạo ra một type (class) có tất cả property của CreateCatDto trừ name, và các property đó sẽ được đặt thành optional:

export class UpdateCatDto extends PartialType(
  OmitType(CreateCatDto, ['name'] as const),
) {}

Ghi chú người dịch Các hàm này chỉ hoạt động đúng khi class gốc dùng decorator @ApiProperty() (hoặc được CLI plugin tự động thêm) — chúng đọc metadata từ decorator, không suy ra từ kiểu TypeScript thuần. Nếu bạn quen với Go, hãy nghĩ nó gần giống việc tạo một struct mới bằng cách embedding một struct khác rồi override lại field, nhưng ở đây Nest làm việc đó tại runtime dựa trên reflection metadata thay vì compile-time.

Nội dung gốc: NestJS Documentation © Kamil Myśliwiec, giấy phép MIT. Bản dịch và ghi chú: Lê Văn Dũng.