Skip to content

Commit

Permalink
add VariantSchema.Union constructor (#3493)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored Aug 20, 2024
1 parent ae53062 commit f2c8dbb
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .changeset/thick-gorillas-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@effect/experimental": patch
"@effect/sql": patch
---

add VariantSchema.Union constructor
61 changes: 60 additions & 1 deletion packages/experimental/src/VariantSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ export const TypeId: unique symbol = Symbol.for("@effect/experimental/VariantSch
*/
export type TypeId = typeof TypeId

const cacheSymbol = Symbol.for("@effect/experimental/VariantSchema/cache")

/**
* @since 1.0.0
* @category models
*/
export interface Struct<in out A extends Field.Fields> extends Pipeable {
readonly [TypeId]: A
/** @internal */
[cacheSymbol]?: Record<string, Schema.Schema.All>
}

/**
Expand Down Expand Up @@ -185,6 +189,11 @@ const extract: {
readonly isDefault?: boolean | undefined
}
): Extract<V, A> => {
const cache = self[cacheSymbol] ?? (self[cacheSymbol] = {})
const cacheKey = options?.isDefault === true ? "__default" : variant
if (cache[cacheKey] !== undefined) {
return cache[cacheKey] as any
}
const fields: Record<string, any> = {}
for (const key of Object.keys(self[TypeId])) {
const value = self[TypeId][key]
Expand All @@ -202,7 +211,7 @@ const extract: {
fields[key] = value
}
}
return Schema.Struct(fields) as any
return cache[cacheKey] = Schema.Struct(fields) as any
}
)

Expand Down Expand Up @@ -269,6 +278,36 @@ type ClassFromFields<
type MissingSelfGeneric<Params extends string = ""> =
`Missing \`Self\` generic - use \`class Self extends Class<Self>()(${Params}{ ... })\``

/**
* @since 1.0.0
* @category models
*/
export interface Union<Members extends ReadonlyArray<Struct<any>>> extends
Schema.Union<
{
readonly [K in keyof Members]: [Members[K]] extends [Schema.Schema.All] ? Members[K] : never
}
>
{}

/**
* @since 1.0.0
* @category models
*/
export declare namespace Union {
/**
* @since 1.0.0
* @category models
*/
export type Variants<Members extends ReadonlyArray<Struct<any>>, Variants extends string> = {
readonly [Variant in Variants]: Schema.Union<
{
[K in keyof Members]: Extract<Variant, Members[K]>
}
>
}
}

/**
* @since 1.0.0
* @category constructors
Expand Down Expand Up @@ -347,6 +386,9 @@ export const make = <
& {
readonly [V in Variants[number]]: Extract<V, Struct<Fields>>
}
readonly Union: <const Members extends ReadonlyArray<Struct<any>>>(
...members: Members
) => Union<Members> & Union.Variants<Members, Variants[number]>
readonly extract: {
<V extends Variants[number]>(
variant: V
Expand Down Expand Up @@ -397,6 +439,9 @@ export const make = <
return Field(obj)
}
}
function UnionVariants(...members: ReadonlyArray<Struct<any>>) {
return Union(members, options.variants)
}
const fieldEvolveVariants = dual(
2,
(
Expand All @@ -422,6 +467,7 @@ export const make = <
FieldOnly,
FieldExcept,
Class,
Union: UnionVariants,
fieldEvolve: fieldEvolveVariants,
extract: extractVariants
} as any
Expand Down Expand Up @@ -481,3 +527,16 @@ const Field = <const A extends Field.Config>(schemas: A): Field<A> => {
self.schemas = schemas
return self
}

const Union = <Members extends ReadonlyArray<Struct<any>>, Variants extends ReadonlyArray<string>>(
members: Members,
variants: Variants
) => {
class VariantUnion extends (Schema.Union(...members.filter((member) => Schema.isSchema(member))) as any) {}
for (const variant of variants) {
Object.defineProperty(VariantUnion, variant, {
value: Schema.Union(...members.map((member) => extract(member, variant)))
})
}
return VariantUnion
}
8 changes: 7 additions & 1 deletion packages/sql/src/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const {
FieldExcept,
FieldOnly,
Struct,
Union,
extract,
fieldEvolve
} = VariantSchema.make({
Expand Down Expand Up @@ -138,7 +139,12 @@ export {
* @since 1.0.0
* @category constructors
*/
Struct
Struct,
/**
* @since 1.0.0
* @category constructors
*/
Union
}

/**
Expand Down

0 comments on commit f2c8dbb

Please sign in to comment.