TypeScript 类型工具与 NestJS Mapped Types

概述

在 NestJS 开发中,我们经常需要创建 DTO(Data Transfer Object)类。NestJS 提供了 @nestjs/mapped-types 包来帮助我们基于现有类创建新的 DTO 类,同时保留装饰器和验证元数据

TypeScript 内置类型工具 vs NestJS Mapped Types

1. PartialType vs Partial

TypeScript 内置 Partial

typescript 复制代码
type Partial<T> = {
  [P in keyof T]?: T[P];
};

// 使用示例
interface User {
  name: string;
  age: number;
}

type PartialUser = Partial<User>;
// 结果:{ name?: string; age?: number; }

特点:

  • 仅用于类型检查,编译后不存在
  • 无法保留装饰器和验证元数据
  • 不能用于 class-validator

NestJS PartialType

typescript 复制代码
import { PartialType } from '@nestjs/mapped-types';

class CreateUserDto {
  @IsString()
  name: string;

  @IsNumber()
  age: number;
}

class UpdateUserDto extends PartialType(CreateUserDto) {}
// 结果:一个类,保留了所有装饰器和验证元数据

特点:

  • 运行时存在,是一个真正的类
  • 保留装饰器和验证元数据
  • 可用于 class-validator 和 NestJS DI

2. PickType vs Pick

TypeScript 内置 Pick

typescript 复制代码
type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

// 使用示例
type UserName = Pick<User, 'name'>;
// 结果:{ name: string; }

NestJS PickType

typescript 复制代码
import { PickType } from '@nestjs/mapped-types';

class UserNameDto extends PickType(CreateUserDto, ['name'] as const) {}
// 结果:一个类,保留了 name 字段的装饰器

3. OmitType vs Omit

TypeScript 内置 Omit

typescript 复制代码
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

// 使用示例
type UserWithoutAge = Omit<User, 'age'>;
// 结果:{ name: string; }

NestJS OmitType

typescript 复制代码
import { OmitType } from '@nestjs/mapped-types';

class UserWithoutAgeDto extends OmitType(CreateUserDto, ['age'] as const) {}
// 结果:一个类,保留了剩余字段的装饰器

关键区别对比

特性 TypeScript 内置类型 NestJS mapped-types
类型 类型别名(Type Alias) 类(Class)
运行时 不存在(编译后消失) 存在(可在运行时使用)
装饰器 无法保留 保留装饰器和验证元数据
验证 无法用于 class-validator 可用于 class-validator
依赖注入 无法用于 DI 可用于 NestJS DI

使用场景

TypeScript 内置类型(适合纯类型操作)

typescript 复制代码
// 仅用于类型检查,不涉及运行时
function updateUser(id: string, data: Partial<User>) {
  // ...
}

NestJS mapped-types(适合 DTO 和验证)

typescript 复制代码
import { Controller, Post, Patch, Body } from '@nestjs/common';
import { PartialType } from '@nestjs/mapped-types';

@Controller('users')
export class UserController {
  @Post()
  create(@Body() dto: CreateUserDto) {
    // class-validator 会自动验证
  }

  @Patch(':id')
  update(@Body() dto: UpdateUserDto) {
    // UpdateUserDto 继承了 CreateUserDto 的所有验证规则
  }
}

最佳实践

  1. DTO 类使用 mapped-types :当需要创建可验证的 DTO 类时,使用 @nestjs/mapped-types
  2. 纯类型操作使用内置类型:当只需要类型层面的操作时,使用 TypeScript 内置类型
  3. 保持一致性:在同一个项目中,保持使用方式的一致性

相关资源

相关推荐
万少2 小时前
HarmonyOS 开发必会 5 种 Builder 详解
前端·harmonyos
橙序员小站4 小时前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
怒放吧德德5 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
雨中飘荡的记忆6 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
炫饭第一名7 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫7 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊7 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter7 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
开心就好20257 小时前
UniApp开发应用多平台上架全流程:H5小程序iOS和Android
后端·ios
曲折8 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium