NestJS子类DTO重写属性遇类型不兼容报错,求解决方法
解决TypeScript枚举继承DTO属性的类型不兼容问题
问题场景
定义基础枚举Status、子集枚举UserStatus,以及包含status属性的通用DTOCommonDto,子类UserDto继承CommonDto并重写status属性为UserStatus类型时,出现类型不兼容报错:
Property 'status' in type 'UserDto' is not assignable to the same property in base type 'CommonDto'. Type 'UserStatus' is not assignable to type 'Status'
相关代码:
// 基础枚举 export enum Status { Active = "Active", Inactive = "Inactive", } // 子集枚举 export enum UserStatus { Active = Status.Active, }; // 通用DTO export class CommonDto { @ApiProperty({ description: "Status", required: true }) status: Status; } // 子类DTO(报错) export class UserDto extends CommonDto { @ApiProperty({ description: "Status", required: true, enum: UserStatus }) status: UserStatus; }
原因分析
TypeScript中,即使两个枚举的成员值完全一致,它们的类型也是独立的。UserStatus和Status是两个不同的枚举类型,因此子类的status属性类型(UserStatus)无法兼容父类的Status类型,违反了类型协变规则。
解决方案
方案1:用类型别名替代子集枚举
将UserStatus从枚举改为类型别名,直接指向Status的子集成员,类型会自动兼容:
// 替换枚举为类型别名 export type UserStatus = Status.Active; // 修改UserDto export class UserDto extends CommonDto { @ApiProperty({ description: "Status", required: true, enum: [Status.Active] // 直接指定枚举成员数组 }) status: UserStatus; }
方案2:泛化CommonDto
将CommonDto改造为泛型类,允许子类指定status的具体类型,确保类型兼容:
// 泛型通用DTO export class CommonDto<T extends Status = Status> { @ApiProperty({ description: "Status", required: true }) status: T; } // 子类DTO指定泛型参数 export class UserDto extends CommonDto<UserStatus> { @ApiProperty({ description: "Status", required: true, enum: UserStatus }) status: UserStatus; }
注意:若使用此方案,需确保
UserStatus的所有成员值都属于Status的成员范围,否则需要调整UserStatus的定义或泛型约束。
方案3:使用类型断言(不推荐)
如果只是临时绕过类型检查,可以使用类型断言,但会丢失TypeScript的类型校验能力:
export class UserDto extends CommonDto { @ApiProperty({ description: "Status", required: true, enum: UserStatus }) status: UserStatus = Status.Active as UserStatus; }
内容的提问来源于stack exchange,提问作者Code Guru
相关产品推荐
相关产品推荐

