Skip to content

Commit

Permalink
Partial Deep Prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Apr 25, 2024
1 parent cfc152b commit 130c520
Showing 1 changed file with 26 additions and 24 deletions.
50 changes: 26 additions & 24 deletions example/prototypes/partial-deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,40 @@ THE SOFTWARE.
import { TypeGuard, Type, TSchema, TIntersect, TUnion, TObject, TPartial, TProperties, Evaluate } from '@sinclair/typebox'

// -------------------------------------------------------------------------------------
// TDeepPartial
// TPartialDeepProperties
// -------------------------------------------------------------------------------------
export type TPartialDeepProperties<T extends TProperties> = {
[K in keyof T]: TPartial<T[K]>
[K in keyof T]: TPartialDeep<T[K]>
}
export type TPartialDeepRest<T extends TSchema[]> =
function PartialDeepProperties<T extends TProperties>(properties: T): TPartialDeepProperties<T> {
return Object.getOwnPropertyNames(properties).reduce((acc, key) => {
return {...acc, [key]: PartialDeep(properties[key])}
}, {}) as never
}
// -------------------------------------------------------------------------------------
// TPartialDeepRest
// -------------------------------------------------------------------------------------
export type TPartialDeepRest<T extends TSchema[], Acc extends TSchema[] = []> = (
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? [TPartial<L>, ...TPartialDeepRest<R>]
: []
? TPartialDeepRest<R, [...Acc, TPartialDeep<L>]>
: Acc
)
function PartialDeepRest<T extends TSchema[]>(rest: [...T]): TPartialDeepRest<T> {
return rest.map(schema => PartialDeep(schema)) as never
}
// -------------------------------------------------------------------------------------
// TPartialDeep
// -------------------------------------------------------------------------------------
export type TPartialDeep<T extends TSchema> =
T extends TIntersect<infer S> ? TIntersect<TPartialDeepRest<S>> :
T extends TUnion<infer S> ? TUnion<TPartialDeepRest<S>> :
T extends TObject<infer S> ? TPartial<TObject<Evaluate<TPartialDeepProperties<S>>>> :
T
// -------------------------------------------------------------------------------------
// DeepPartial
// -------------------------------------------------------------------------------------
function PartialDeepProperties<T extends TProperties>(properties: T) {
return Object.getOwnPropertyNames(properties).reduce((acc, key) => {
return {...acc, [key]: Type.Partial(properties[key])}
}, {} as TProperties)
}
function PartialDeepRest<T extends TSchema[]>(rest: [...T]): TPartialDeepRest<T> {
const [L, ...R] = rest
return (R.length > 0) ? [Type.Partial(L), ...PartialDeepRest(R)] : [] as any
}
/** Maps the given schema as deep partial, making all properties and sub properties optional */
export function PartialDeep<T extends TSchema>(type: T): TPartialDeep<T> {
export function PartialDeep<T extends TSchema>(schema: T): TPartialDeep<T> {
return (
TypeGuard.IsIntersect(type) ? Type.Intersect(PartialDeepRest(type.allOf)) :
TypeGuard.IsUnion(type) ? Type.Union(PartialDeepRest(type.anyOf)) :
TypeGuard.IsObject(type) ? Type.Partial(Type.Object(PartialDeepProperties(type.properties))) :
type
) as any
TypeGuard.IsIntersect(schema) ? Type.Intersect(PartialDeepRest(schema.allOf)) :
TypeGuard.IsUnion(schema) ? Type.Union(PartialDeepRest(schema.anyOf)) :
TypeGuard.IsObject(schema) ? Type.Partial(Type.Object(PartialDeepProperties(schema.properties))) :
schema
) as never
}

0 comments on commit 130c520

Please sign in to comment.