diff --git a/packages/farrow-schema/src/helper.ts b/packages/farrow-schema/src/helper.ts index 6b0b3f4..4117b82 100644 --- a/packages/farrow-schema/src/helper.ts +++ b/packages/farrow-schema/src/helper.ts @@ -51,60 +51,68 @@ export const omitStruct = ) } -export type PickObject> = { - [key in keyof T as key extends Keys ? key : never]: T[key] extends FieldDescriptor ? T[key] : never -} - +export type PickObject[]> = new () => { + [K in Keys[number]]: T[K] extends FieldDescriptor ? T[K] : T[K] extends S.SchemaCtorInput ? T[K] : never +} & ObjectType export const pickObject = []>( Ctor: new () => T, keys: Keys, ) => { const instance = getInstance(Ctor) - const descriptors = {} as FieldDescriptors - if (instance instanceof ObjectType) { - for (const key of Object.keys(instance)) { - if (keys.includes(key as any)) { - // @ts-ignore - const value = instance[key] - if (isFieldDescriptor(value)) { - descriptors[key] = value - } else if (isFieldDescriptors(value)) { - descriptors[key] = value + return class PickedObject extends ObjectType { + constructor() { + super() + if (instance instanceof ObjectType) { + for (const key of Object.keys(instance)) { + if (keys.includes(key as any)) { + // @ts-ignore + const value = instance[key] + if (isFieldDescriptor(value) || isFieldDescriptors(value)) { + Object.defineProperty(this, key, { + enumerable: true, + value: value, + }) + } + } } } } - } - - return Struct(descriptors as PickObject) + } as PickObject } -export type OmitObject> = { - [key in keyof T as key extends Keys | '__type' ? never : key]: T[key] extends FieldDescriptor ? T[key] : never -} +export type OmitObject[]> = new () => { + [K in keyof T as K extends Keys[number] | '__type' ? never : K]: T[K] extends FieldDescriptor + ? T[K] + : T[K] extends S.SchemaCtorInput + ? T[K] + : never +} & ObjectType export const omitObject = []>( Ctor: new () => T, keys: Keys, ) => { const instance = getInstance(Ctor) - const descriptors = {} as FieldDescriptors - - if (instance instanceof ObjectType) { - for (const key of Object.keys(instance)) { - if (!keys.includes(key as any)) { - // @ts-ignore - const value = instance[key] - if (isFieldDescriptor(value)) { - descriptors[key] = value - } else if (isFieldDescriptors(value)) { - descriptors[key] = value + return class OmittedObject extends ObjectType { + constructor() { + super() + if (instance instanceof ObjectType) { + for (const key of Object.keys(instance)) { + if (!keys.includes(key as any)) { + // @ts-ignore + const value = instance[key] + if (isFieldDescriptor(value) || isFieldDescriptors(value)) { + Object.defineProperty(this, key, { + enumerable: true, + value: value, + }) + } + } } } } - } - - return Struct(descriptors as OmitObject) + } as OmitObject } export type PickSchema = typeof pickObject & typeof pickStruct @@ -222,12 +230,34 @@ export const partialStruct = (Ctor: new () => T) => { } } +export type PartialObjectType = new () => { + [K in keyof T as K extends '__type' ? never : K]?: T[K] extends FieldDescriptor + ? T[K] + : T[K] extends S.SchemaCtorInput + ? T[K] + : never +} & ObjectType export const partialObject = (Ctor: new () => T) => { const instance = getInstance(Ctor) - return class partial extends PartialType { - Item = S.Struct(getPartialFields(instance as unknown as S.FieldDescriptors)) as unknown as typeof Ctor - } + return class PartialObject extends ObjectType { + constructor() { + super() + if (instance instanceof ObjectType) { + for (const key of Object.keys(instance)) { + // @ts-ignore + const value = instance[key] + if (isFieldDescriptor(value) || isFieldDescriptors(value)) { + Object.defineProperty(this, key, { + enumerable: true, + // @ts-ignore + value: isNullableType(value) ? value : S.Nullable(value), + }) + } + } + } + } + } as unknown as PartialObjectType } export const partial: typeof partialStruct & typeof partialObject = ( @@ -243,3 +273,78 @@ export const partial: typeof partialStruct & typeof partialObject = ( throw new Error(`Unknown Schema Constructor: ${Ctor}`) } + +const getRequiredFields = (fields: FieldDescriptors): FieldDescriptors => { + const descriptors = {} as FieldDescriptors + + for (const [key, value] of Object.entries(fields)) { + if (isFieldDescriptor(value)) { + descriptors[key] = isNullableType(value) ? (value as any).Item : value + } else if (isFieldDescriptors(value)) { + descriptors[key] = getRequiredFields(value) + } + } + + return descriptors +} + +export const requiredStruct = (Ctor: new () => T) => { + const instance = getInstance(Ctor) + const descriptors = {} as FieldDescriptors + + // 遍历所有字段 + for (const [key, value] of Object.entries(instance.descriptors)) { + if (isFieldDescriptor(value)) { + // 如果是可空类型,获取其原始类型 + descriptors[key] = isNullableType(value) ? (value as any).Item : value + } else if (isFieldDescriptors(value)) { + // 如果是嵌套对象,递归处理 + descriptors[key] = getRequiredFields(value) + } + } + + return Struct(descriptors) +} + +export type RequiredObjectType = new () => { + [K in keyof T as K extends '__type' ? never : K]: T[K] extends FieldDescriptor + ? T[K] + : T[K] extends S.SchemaCtorInput + ? T[K] + : never +} & ObjectType + +export const requiredObject = (Ctor: new () => T) => { + const instance = getInstance(Ctor) + + return class RequiredObject extends ObjectType { + constructor() { + super() + if (instance instanceof ObjectType) { + for (const key of Object.keys(instance)) { + const value = instance[key] + if (isFieldDescriptor(value) || isFieldDescriptors(value)) { + Object.defineProperty(this, key, { + enumerable: true, + value: isNullableType(value) ? value.Item : value, + }) + } + } + } + } + } as RequiredObjectType +} + +export const required: typeof requiredStruct & typeof requiredObject = ( + Ctor: new () => S.ObjectType | S.StructType, +): any => { + if (Ctor?.prototype instanceof ObjectType) { + return requiredObject(Ctor as any) + } + + if (Ctor?.prototype instanceof StructType) { + return requiredStruct(Ctor as any) + } + + throw new Error(`Unknown Schema Constructor: ${Ctor}`) +} \ No newline at end of file