Working new implementation
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Julien Valverdé
2024-01-21 22:58:44 +01:00
parent 6873fae86b
commit c073154eeb
4 changed files with 93 additions and 131 deletions

64
src/TZodSchemaClass.ts Normal file
View File

@@ -0,0 +1,64 @@
import { Class as ConcreteClass, HasRequiredKeys } from "type-fest"
import { z } from "zod"
import { Class, ClassType } from "./util"
export type NewZodSchemaInstanceInput<
Values extends {},
DefaultValues extends Partial<Values>,
> = {
[Key in Exclude<keyof Values, keyof DefaultValues>]: Values[Key]
} & {
[Key in keyof DefaultValues]?: Key extends keyof Values
? Values[Key]
: never
}
export type ParseParamsArgs = [] | [params: Partial<z.ParseParams>]
export type NewZodSchemaInstanceArgs<Input extends object> =
HasRequiredKeys<Input> extends true
? [values: Input, ...args: ParseParamsArgs]
: [] | [values: Input, ...args: ParseParamsArgs]
export type TZodSchemaClass<
Schema extends z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>,
SchemaT extends z.ZodRawShape,
SchemaUnknownKeys extends z.UnknownKeysParam,
SchemaCatchall extends z.ZodTypeAny,
Values extends {},
DefaultValues extends Partial<Values>,
Type extends ClassType = "AbstractClass"
> = (
Class<
Type,
Values,
[values: Values]
> & {
readonly schema: Schema
readonly defaultValues: DefaultValues
newPromise<Self extends ConcreteClass<any>>(
this: Self,
...[values, params]: NewZodSchemaInstanceArgs<
NewZodSchemaInstanceInput<Values, DefaultValues>
>
): Promise<InstanceType<Self>>
newEffect<Self extends ConcreteClass<any>>(
this: Self,
...[values, params]: NewZodSchemaInstanceArgs<
NewZodSchemaInstanceInput<Values, DefaultValues>
>
): Promise<InstanceType<Self>>
extend<
Parent
>(
this: Parent
): Parent
}
)

View File

@@ -1,40 +1,9 @@
import { AbstractClass, Class as ConcreteClass, Opaque } from "type-fest" import { AbstractClass, Class as ConcreteClass, Opaque } from "type-fest"
import { z } from "zod" import { z } from "zod"
import { DefinedDefaultValuesTag } from "." import { DefinedDefaultValuesTag, NewZodSchemaInstanceArgs, NewZodSchemaInstanceInput, TZodSchemaClass } from "."
import { StaticMembers } from "./util" import { StaticMembers } from "./util"
export type TZodSchemaClass<
Schema extends z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>,
SchemaT extends z.ZodRawShape,
SchemaUnknownKeys extends z.UnknownKeysParam,
SchemaCatchall extends z.ZodTypeAny,
Values extends {},
DefaultValues extends Partial<Values>,
> = (
AbstractClass<
{
readonly schema: Schema
readonly defaultValues: DefaultValues
} & Values,
[values: Values]
> & {
readonly schema: Schema
readonly defaultValues: DefaultValues
newPromise<Self extends ConcreteClass<any>>(this: Self): Promise<InstanceType<Self>>
extend<
Parent
>(
this: Parent
): Parent
}
)
type ExtendableClass = AbstractClass<{ type ExtendableClass = AbstractClass<{
schema?: never schema?: never
defaultValues?: never defaultValues?: never
@@ -43,8 +12,7 @@ type ExtendableClass = AbstractClass<{
defaultValues?: never defaultValues?: never
} }
function makeClass< export function ZodSchemaClassOf<
Self,
Parent extends ExtendableClass, Parent extends ExtendableClass,
Schema extends z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>, Schema extends z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>,
@@ -55,9 +23,9 @@ function makeClass<
Values extends {}, Values extends {},
DefaultValues extends Partial<Values>, DefaultValues extends Partial<Values>,
>( >(
{ of, schema, defaultValues }: {
self: Self,
of: Parent, of: Parent,
{ schema, defaultValues }: {
schema: Schema | z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values> schema: Schema | z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>
defaultValues: Opaque<DefaultValues, DefinedDefaultValuesTag> defaultValues: Opaque<DefaultValues, DefinedDefaultValuesTag>
}, },
@@ -68,7 +36,7 @@ function makeClass<
: AbstractClass<T, Arguments> : AbstractClass<T, Arguments>
) )
type ZodClass = TZodSchemaClass< type TZodSchemaClassImpl = TZodSchemaClass<
Schema, Schema,
SchemaT, SchemaT,
SchemaUnknownKeys, SchemaUnknownKeys,
@@ -80,97 +48,31 @@ function makeClass<
return class extends (of as unknown as ConcreteClass<any, []>) { return class extends (of as unknown as ConcreteClass<any, []>) {
static readonly schema = schema static readonly schema = schema
readonly schema = schema
static readonly defaultValues = defaultValues static readonly defaultValues = defaultValues
readonly defaultValues = defaultValues
constructor(values: Values) { constructor(values: Values) {
super() super()
Object.assign(this, values) Object.assign(this, values)
} }
static async newPromise(
...[values, params]: NewZodSchemaInstanceArgs<
NewZodSchemaInstanceInput<Values, DefaultValues>
>
) {
return new this(
await this.schema.parseAsync({ ...this.defaultValues, ...values }, params)
)
}
} as unknown as ( } as unknown as (
Class< Class<
InstanceType<Parent> & InstanceType<Parent> &
InstanceType<ZodClass>, InstanceType<TZodSchemaClassImpl>,
ConstructorParameters<ZodClass> ConstructorParameters<TZodSchemaClassImpl>
> & > &
StaticMembers<Parent> & StaticMembers<Parent> &
StaticMembers<ZodClass> StaticMembers<TZodSchemaClassImpl>
) )
} }
export function ZodSchemaClassOf<Self>() {
return <
Parent extends ExtendableClass,
Schema extends z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>,
SchemaT extends z.ZodRawShape,
SchemaUnknownKeys extends z.UnknownKeysParam,
SchemaCatchall extends z.ZodTypeAny,
Values extends {},
DefaultValues extends Partial<Values>,
>(
of: Parent,
props: Omit<
Parameters<
typeof makeClass<
Self,
Parent,
Schema,
SchemaT,
SchemaUnknownKeys,
SchemaCatchall,
Values,
DefaultValues
>
>[0], "self" | "of"
>,
) => makeClass({
...props,
self: {} as Self,
of,
})
}
const DefaultParent = Object
export function ZodSchemaClass<Self>() {
return <
Schema extends z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>,
SchemaT extends z.ZodRawShape,
SchemaUnknownKeys extends z.UnknownKeysParam,
SchemaCatchall extends z.ZodTypeAny,
Values extends {},
DefaultValues extends Partial<Values>,
>(
props: Omit<
Parameters<
typeof makeClass<
Self,
typeof DefaultParent,
Schema,
SchemaT,
SchemaUnknownKeys,
SchemaCatchall,
Values,
DefaultValues
>
>[0], "self" | "of"
>,
) => makeClass({
...props,
self: {} as Self,
of: DefaultParent,
})
}

View File

@@ -1,2 +1,3 @@
export * from "./TZodSchemaClass"
export * from "./ZodSchemaClass" export * from "./ZodSchemaClass"
export * from "./defineDefaultValues" export * from "./defineDefaultValues"

View File

@@ -2,25 +2,20 @@ import { z } from "zod"
import { ZodSchemaClassOf, defineDefaultValues } from "." import { ZodSchemaClassOf, defineDefaultValues } from "."
class Test extends ZodSchemaClassOf<Test>()(Object, { class Test extends ZodSchemaClassOf(Object, {
schema: z.object({ schema: z.object({
id: z.bigint() id: z.bigint(),
name: z.string(),
}), }),
defaultValues: defineDefaultValues({ id: -1n }), defaultValues: defineDefaultValues({ id: -1n }),
}) {} }) {}
Test.newPromise() Test.defaultValues
Test.extend() const inst = await Test.newPromise({ id: 1n, name: "" })
// Test.extend()
new Test({ id: 1n }).id console.log(inst)
// class ChildTest extends Test {}
const Test2 = ZodSchemaClassOf<Test>()(Object, { // ChildTest.newPromise()
schema: z.object({
id: z.bigint()
}),
defaultValues: defineDefaultValues({ id: -1n }),
})
Test2.extend()