如何在TypeScript中将类的所有属性设为可选类型
在TypeScript中将类的所有属性设为可选(支持装饰器)
为什么直接继承Partial<CreateDTO>不行
Partial<T>是TypeScript的映射类型,仅作用于编译时的类型系统,它返回的是一个描述属性可选的类型,而非可被继承的类。类的继承只能针对具体的类(运行时存在的构造函数),因此无法直接继承Partial<CreateDTO>。
可行解决方案
因为需要给属性添加验证装饰器(运行时特性),必须显式定义类的属性,以下是几种常用方案:
方案1:手动标记属性为可选并实现Partial<CreateDTO>
直接在UpdateDTO中定义所有属性并添加?标记,同时实现Partial<CreateDTO>来保证类型与原类对齐,再给属性添加装饰器:
// 假设使用class-validator做验证 import { IsOptional, IsString, IsNumber } from 'class-validator'; class CreateDTO { @IsString() id: string; @IsString() name: string; @IsNumber() price: number; } class UpdateDTO implements Partial<CreateDTO> { @IsOptional() @IsString() id?: string; @IsOptional() @IsString() name?: string; @IsOptional() @IsNumber() price?: number; }
方案2:封装装饰器减少重复代码
如果属性较多,可封装组合装饰器来避免重复写@IsOptional()和验证装饰器:
import { IsOptional, IsString, IsNumber, ValidationOptions } from 'class-validator'; // 封装可选字符串装饰器 function OptionalString(options?: ValidationOptions) { return function (target: any, propertyKey: string) { IsOptional()(target, propertyKey); IsString(options)(target, propertyKey); }; } // 封装可选数字装饰器 function OptionalNumber(options?: ValidationOptions) { return function (target: any, propertyKey: string) { IsOptional()(target, propertyKey); IsNumber(options)(target, propertyKey); }; } class CreateDTO { @IsString() id: string; @IsString() name: string; @IsNumber() price: number; } class UpdateDTO implements Partial<CreateDTO> { @OptionalString() id?: string; @OptionalString() name?: string; @OptionalNumber() price?: number; }
方案3:继承原类并重写属性为可选(需处理父类构造函数)
如果需要继承原类的方法或其他逻辑,可重写属性为可选,但要注意父类构造函数的必填参数问题:
class CreateDTO { id: string; name: string; price: number; constructor(id: string, name: string, price: number) { this.id = id; this.name = name; this.price = price; } } class UpdateDTO extends CreateDTO { id?: string; name?: string; price?: number; constructor(id?: string, name?: string, price?: number) { // 父类构造函数需要必填参数,需传入默认值占位 super(id ?? '', name ?? '', price ?? 0); // 覆盖父类属性值 this.id = id; this.name = name; this.price = price; } }
关键说明
- 装饰器是运行时特性,必须显式定义类的属性才能添加装饰器,无法通过纯类型操作自动生成带装饰器的可选属性。
- 使用
implements Partial<CreateDTO>可以确保UpdateDTO的属性结构与原类一致,避免手动定义时出现遗漏或类型错误。
内容的提问来源于stack exchange,提问作者Miguel
相关产品推荐
相关产品推荐

