Chuyển đến nội dung chính

レッスン 2: NestJS の TypeScript の基礎

NestJS の重要な TypeScript (デコレータ、ジェネリック、インターフェイス、列挙型、タイプ ガード、ユーティリティ タイプ) を確認します。 NestJS プロジェクトの tsconfig.json を構成します。

💻 プログラミング — レッスン 2 レッスン 2: NestJS の TypeScript の基礎

NestJS: 基本から高度まで

パート 1: NestJS プラットフォーム

xdev.asia

1. NestJS にとって TypeScript が重要なのはなぜですか?

NestJS は完全に TypeScript を使用して構築されており、次のような TypeScript の高度な機能を最大限に活用しています。 デコレーター、 メタデータの反映、 ジェネリック。 TypeScript を理解すると、NestJS をより効率的に操作できるようになります。

2. デコレータ — NestJS の中心部

デコレータは、NestJS で最もよく使用される TypeScript 機能です。彼らは、 特別な機能 クラス、メソッド、プロパティ、またはパラメーターにアタッチしてメタデータを追加します。

クラスデコレータ

// Class Decorator
function Controller(prefix: string) {
  return function (target: Function) {
    Reflect.defineMetadata('prefix', prefix, target);
  };
}

@Controller('/users')
class UsersController {
  // NestJS tự biết controller này handle route /users
}

メソッドデコレータ

// Method Decorator
function Log(target: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${key} with args:`, args);
    const result = original.apply(this, args);
    console.log(`Result:`, result);
    return result;
  };
}

class UserService {
  @Log
  findUser(id: number) {
    return { id, name: 'John' };
  }
}

パラメータデコレータ

// Trong NestJS, bạn sẽ gặp:
@Get(':id')
findOne(
  @Param('id') id: string,           // Parameter decorator
  @Query('include') include: string,  // Parameter decorator
  @Body() body: CreateUserDto,        // Parameter decorator
) {
  // ...
}

デコレータ構成

// Kết hợp nhiều decorators
function Auth(...roles: string[]) {
  return applyDecorators(
    UseGuards(AuthGuard('jwt'), RolesGuard),
    Roles(...roles),
    ApiBearerAuth(),
  );
}

@Auth('admin')
@Get('admin/dashboard')
getDashboard() { ... }

3. インターフェースと型エイリアス

// Interface — mở rộng được, dùng cho object shapes
interface User {
  id: number;
  name: string;
  email: string;
  role: UserRole;
  createdAt: Date;
}

// Extending interfaces
interface AdminUser extends User {
  permissions: string[];
  lastLogin: Date;
}

// Type alias — linh hoạt hơn, dùng cho unions, tuples
type UserRole = 'admin' | 'editor' | 'viewer';
type ApiResponse<T> = {
  data: T;
  meta: { total: number; page: number };
};

// Trong NestJS, dùng interface cho DTOs shape, class cho validation

4. ジェネリック — コードの再利用

// Generic function
function wrapResponse<T>(data: T): ApiResponse<T> {
  return { data, meta: { total: 1, page: 1 } };
}

// Generic class — pattern phổ biến trong NestJS Repository
class BaseRepository<T> {
  private items: T[] = [];

  findAll(): T[] {
    return this.items;
  }

  findById(id: number): T | undefined {
    return this.items.find((item: any) => item.id === id);
  }

  create(item: T): T {
    this.items.push(item);
    return item;
  }
}

// Sử dụng
class UserRepository extends BaseRepository<User> {
  findByEmail(email: string): User | undefined {
    return this.findAll().find(u => u.email === email);
  }
}

// Generic constraints
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

5.列挙型

// String enum — dùng nhiều trong NestJS
enum UserRole {
  Admin = 'ADMIN',
  Editor = 'EDITOR', 
  Viewer = 'VIEWER',
}

// Const enum — tối ưu performance
const enum HttpStatus {
  OK = 200,
  Created = 201,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
}

// Sử dụng trong NestJS
@Roles(UserRole.Admin)
@Get('admin')
adminOnly() { ... }

6. 一般的に使用されるユーティリティの種類

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  avatar?: string;
}

// Partial — tất cả fields optional (dùng cho Update DTO)
type UpdateUserDto = Partial<User>;

// Pick — chọn một số fields
type UserPublicInfo = Pick<User, 'id' | 'name' | 'avatar'>;

// Omit — loại bỏ fields (ẩn password)
type UserResponse = Omit<User, 'password'>;

// Record — key-value mapping
type UserPermissions = Record<string, boolean>;

// Required — tất cả fields bắt buộc
type StrictUser = Required<User>;

// NestJS PartialType, PickType, OmitType từ @nestjs/mapped-types
// làm tương tự nhưng giữ validation decorators
import { PartialType, OmitType } from '@nestjs/mapped-types';
class UpdateUserDto extends PartialType(CreateUserDto) {}
class UserResponseDto extends OmitType(CreateUserDto, ['password']) {}

7. タイプガードとナローイング

// typeof guard
function processInput(input: string | number) {
  if (typeof input === 'string') {
    return input.toUpperCase(); // TypeScript biết đây là string
  }
  return input.toFixed(2); // TypeScript biết đây là number
}

// instanceof guard
class HttpException {
  constructor(public message: string, public status: number) {}
}

class NotFoundException extends HttpException {
  constructor(resource: string) {
    super(`${resource} not found`, 404);
  }
}

function handleError(error: Error | HttpException) {
  if (error instanceof HttpException) {
    return { statusCode: error.status, message: error.message };
  }
  return { statusCode: 500, message: 'Internal Server Error' };
}

// Custom type guard
interface AdminUser { role: 'admin'; permissions: string[] }
interface RegularUser { role: 'user'; subscription: string }

function isAdmin(user: AdminUser | RegularUser): user is AdminUser {
  return user.role === 'admin';
}

8. NestJS 用に tsconfig.json を構成する

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "strictBindCallApply": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "paths": {
      "@/*": ["src/*"],
      "@modules/*": ["src/modules/*"],
      "@common/*": ["src/common/*"]
    }
  }
}

NestJS の 2 つの最も重要なオプション:

  • EmitDecoratorMetadata: true — TypeScript がデコレーターのメタデータを出力できるようにします (NestJS DI が必要です)
  • 実験的デコレータ: true — デコレータを有効にする

9. まとめ

この記事では、NestJS に必要な核となる TypeScript 機能を学習しました。

  • デコレーター: クラス、メソッド、パラメータのデコレータ — NestJS の基礎
  • インターフェースとタイプ: データの形状を定義します
  • ジェネリック: 再利用可能でタイプセーフなコードを作成する
  • 列挙型: 定数の定義
  • ユーティリティの種類: DTO の場合は部分、選択、省略
  • タイプガード:絞り込みタイプが安全

次のレッスンでは、NestJS CLI をインストールし、最初のプロジェクトを作成します。