import { IDtoDefine } from "./types" type DeepOptional = { [K in keyof T]?: T[K] extends object ? DeepOptional : T[K] } type DeepNullable = { [K in keyof T]: T[K] extends object ? DeepNullable | null : T[K] | null } type DeepRequired = { [K in keyof T]-?: T[K] extends object ? DeepRequired : T[K] } /** * 将 DTO 定义的所有字段转换为可选(optional) * * @example * class DtoUser { * name = dto.String() * age = dto.Number() * } * * // 转换为所有字段可选 * const DtoPartialUser = dto.toOptional(DtoUser) * * // 验证时 name 和 age 都可以为 undefined * dtoVerify(DtoPartialUser, {}) // OK */ export function dtoToOptional any>(dtoClass: T): DeepOptional> export function dtoToOptional>(dtoObject: T): DeepOptional export function dtoToOptional(dtoDefine: any): any { return convertDto(dtoDefine, "optional") } /** * 将 DTO 定义的所有字段转换为可空(nullable) * * @example * class DtoUser { * name = dto.String() * age = dto.Number() * } * * // 转换为所有字段可空 * const DtoNullableUser = dto.toNullable(DtoUser) * * // 验证时 name 和 age 都可以为 null * dtoVerify(DtoNullableUser, { name: null, age: null }) // OK */ export function dtoToNullable any>(dtoClass: T): DeepNullable> export function dtoToNullable>(dtoObject: T): DeepNullable export function dtoToNullable(dtoDefine: any): any { return convertDto(dtoDefine, "nullable") } /** * 将 DTO 定义的所有字段转换为必需(required),移除 optional 和 nullable 标记 * * @example * class DtoUser { * name? = dto.optional.String() * age? = dto.optional.Number() * } * * // 转换为所有字段必需 * const DtoRequiredUser = dto.toRequired(DtoUser) * * // 验证时 name 和 age 都必须提供 * dtoVerify(DtoRequiredUser, {}) // Error * dtoVerify(DtoRequiredUser, { name: 'test', age: 18 }) // OK */ export function dtoToRequired any>(dtoClass: T): DeepRequired> export function dtoToRequired>(dtoObject: T): DeepRequired export function dtoToRequired(dtoDefine: any): any { return convertDto(dtoDefine, "required") } type ConvertMode = "optional" | "nullable" | "required" function convertDto(dtoDefine: any, mode: ConvertMode): any { // 处理 class 定义 if (typeof dtoDefine === "function" && dtoDefine?.prototype?.constructor) { try { dtoDefine = new dtoDefine() } catch (e) { return dtoDefine } } // 如果是 DTO 定义对象 if (dtoDefine?.__isDto__) { return convertDtoDefine(dtoDefine, mode) } // 如果是普通对象,递归处理每个字段 if (typeof dtoDefine === "object" && dtoDefine !== null && !Array.isArray(dtoDefine)) { const result: Record = {} for (const key in dtoDefine) { result[key] = convertDto(dtoDefine[key], mode) } return result } // 如果是数组(如 [dto.String()]) if (Array.isArray(dtoDefine)) { return dtoDefine.map((item) => convertDto(item, mode)) } return dtoDefine } function convertDtoDefine(dto: IDtoDefine, mode: ConvertMode): IDtoDefine { // 创建新的 DTO 对象副本 const newDto: IDtoDefine = { ...dto } // 根据模式设置标记 switch (mode) { case "optional": newDto.isOptional = true newDto.isNullable = false break case "nullable": newDto.isNullable = true newDto.isOptional = false break case "required": newDto.isOptional = false newDto.isNullable = false break } // 递归处理嵌套的 list(如 Array 类型) if (dto.list) { newDto.list = dto.list.map((item) => convertDto(item, mode)) } // 递归处理嵌套的 nest(如 Object 类型) if (dto.nest) { newDto.nest = convertDto(dto.nest, mode) } return newDto }