import { AbstractClass, Class as ConcreteClass, Opaque } from "type-fest" import { z } from "zod" import { DefinedDefaultValuesTag } from "." import { StaticMembers } from "./util" export function makeSchemableClassFrom< C extends AbstractClass<{ schema?: never defaultValues?: never }, []> & { schema?: never defaultValues?: never }, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends {}, DefaultValues extends Partial, >( extend: C, { schema, defaultValues }: { schema: z.ZodObject defaultValues: Opaque }, ) { type Class = ( C extends ConcreteClass ? ConcreteClass : AbstractClass ) return class extends (extend as unknown as ConcreteClass) { static readonly schema = schema readonly schema = schema static readonly defaultValues = defaultValues readonly defaultValues = defaultValues constructor(values: Values) { super() Object.assign(this, values) } } as unknown as ( Class< InstanceType & { readonly schema: z.ZodObject, readonly defaultValues: DefaultValues, } & Values, Parameters<(values: Values) => void> > & StaticMembers & { readonly schema: z.ZodObject, readonly defaultValues: DefaultValues, } ) } export function makeSchemableClass< SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends {}, DefaultValues extends Partial, >( props: { schema: z.ZodObject defaultValues: Opaque } ) { return makeSchemableClassFrom(Object, props) }