EffectSchemaTraitExpressionBuilder
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Julien Valverdé
2024-05-09 02:10:56 +02:00
parent 4ff193ea96
commit 90bb907db2
4 changed files with 166 additions and 82 deletions

View File

@@ -1,7 +1,8 @@
import { unique } from "remeda"
import { AbstractClass, IsEqual } from "type-fest"
import { AbstractClass } from "type-fest"
import { Trait, TraitTuple } from "./Trait"
import { TraitExpression } from "./TraitExpression"
import { SpreadSupertraits, spreadSupertraits } from "./spreadSupertraits"
import { TraitsUnique, traitsUnique } from "./traitsUnique"
import { Extendable, StaticMembers } from "./util"
@@ -9,56 +10,18 @@ export class TraitExpressionBuilder<
Superclass extends AbstractClass<object>,
const Traits extends readonly Trait<any, any, any, any>[],
> {
declare ["constructor"]: typeof TraitExpressionBuilder
constructor(
readonly expressionSuperclass: Superclass,
readonly expressionTraits: Traits,
) {}
static spreadSupertraits<
const T extends readonly Trait<
TraitExpression<
typeof TraitExpression.NullSuperclass,
readonly Trait<any, any, any, any>[]
>,
any,
any,
any
>[]
>(
traits: T
) {
return traits.flatMap(trait => [
...trait.superExpression.traits,
trait,
]) as readonly Trait<any, any, any, any>[] as TraitExpressionBuilder.SpreadSupertraits<T>
}
static traitsUnique<
const T extends readonly Trait<
TraitExpression<
typeof TraitExpression.NullSuperclass,
readonly Trait<any, any, any, any>[]
>,
any,
any,
any
>[]
>(
traits: T
) {
return unique(traits) as readonly Trait<any, any, any, any>[] as TraitExpressionBuilder.TraitsUnique<T>
}
extends<
Super extends AbstractClass<object>
>(
superclass: Super
) {
return new this.constructor(
return new TraitExpressionBuilder(
superclass,
this.expressionTraits,
)
@@ -80,12 +43,12 @@ export class TraitExpressionBuilder<
Superclass,
TraitExpressionBuilder.ExpressesReturnTypeTraits<Traits, T>
> {
return new this.constructor(
return new TraitExpressionBuilder(
this.expressionSuperclass,
this.constructor.traitsUnique([
traitsUnique([
...this.expressionTraits,
...this.constructor.spreadSupertraits(traits),
...spreadSupertraits(traits),
]),
)
}
@@ -106,11 +69,11 @@ export class TraitExpressionBuilder<
Superclass,
TraitExpressionBuilder.ExpressesFirstReturnTypeTraits<Traits, T>
> {
return new this.constructor(
return new TraitExpressionBuilder(
this.expressionSuperclass,
this.constructor.traitsUnique([
...this.constructor.spreadSupertraits(traits),
traitsUnique([
...spreadSupertraits(traits),
...this.expressionTraits,
]),
)
@@ -141,44 +104,13 @@ export class TraitExpressionBuilder<
}
export namespace TraitExpressionBuilder {
export type SpreadSupertraits<Traits> = (
Traits extends readonly [
infer El extends Trait<any, any, any, any>,
...infer Rest,
]
? readonly [
...Trait.Supertraits<El>,
El,
...SpreadSupertraits<Rest>,
]
: readonly []
)
export type TraitsUnique<Traits> = (
Traits extends readonly [
...infer Rest,
infer El extends Trait<any, any, any, any>,
]
? IsTraitInTupleFromRight<Rest, El> extends true
? TraitsUnique<Rest>
: readonly [...TraitsUnique<Rest>, El]
: readonly []
)
type IsTraitInTupleFromRight<Traits, T> = (
Traits extends readonly [...infer Rest, infer El]
? IsEqual<El, T> extends true
? true
: IsTraitInTupleFromRight<Rest, T>
: false
)
export type ExpressesReturnTypeTraits<
Traits extends readonly Trait<any, any, any, any>[],
T extends readonly Trait<any, any, any, any>[],
> = (
TraitExpressionBuilder.TraitsUnique<readonly [
TraitsUnique<readonly [
...Traits,
...TraitExpressionBuilder.SpreadSupertraits<T>,
...SpreadSupertraits<T>,
]>
)
@@ -186,8 +118,8 @@ export namespace TraitExpressionBuilder {
Traits extends readonly Trait<any, any, any, any>[],
T extends readonly Trait<any, any, any, any>[],
> = (
TraitExpressionBuilder.TraitsUnique<readonly [
...TraitExpressionBuilder.SpreadSupertraits<T>,
TraitsUnique<readonly [
...SpreadSupertraits<T>,
...Traits,
]>
)

View File

@@ -0,0 +1,78 @@
import { Schema as S } from "@effect/schema"
import { Trait } from "../Trait"
import { TraitExpression } from "../TraitExpression"
import { TraitExpressionBuilder } from "../TraitExpressionBuilder"
import { spreadSupertraits } from "../spreadSupertraits"
import { traitsUnique } from "../traitsUnique"
export class EffectSchemaTraitExpressionBuilder<
Superclass extends S.Class<unknown, Fields, A, I, R, C, Inherited, Proto>,
const Traits extends readonly Trait<any, any, any, any>[],
Fields extends S.Struct.Fields,
A, I, R, C,
Inherited extends object,
Proto,
> {
constructor(
readonly expressionSuperclass: Superclass,
readonly expressionTraits: Traits,
) {}
extends<
Super extends S.Class<unknown, SuperFields, SuperA, SuperI, SuperR, SuperC, SuperInherited, SuperProto>,
SuperFields extends S.Struct.Fields,
SuperA, SuperI, SuperR, SuperC,
SuperInherited extends object,
SuperProto,
>(
superclass: Super | S.Class<unknown, SuperFields, SuperA, SuperI, SuperR, SuperC, SuperInherited, SuperProto>
) {
return new EffectSchemaTraitExpressionBuilder<
Super,
Traits,
SuperFields,
SuperA, SuperI, SuperR, SuperC,
SuperInherited,
SuperProto
>(
superclass as Super,
this.expressionTraits,
)
}
expresses<
const T extends readonly Trait<
TraitExpression<
typeof TraitExpression.NullSuperclass,
readonly Trait<any, any, any, any>[]
>,
any,
any,
any
>[]
>(
...traits: T
): EffectSchemaTraitExpressionBuilder<
Superclass,
TraitExpressionBuilder.ExpressesReturnTypeTraits<Traits, T>,
Fields,
A, I, R, C,
Inherited,
Proto
> {
return new EffectSchemaTraitExpressionBuilder(
this.expressionSuperclass,
traitsUnique([
...this.expressionTraits,
...spreadSupertraits(traits),
]),
)
}
}

35
src/spreadSupertraits.ts Normal file
View File

@@ -0,0 +1,35 @@
import { Trait } from "./Trait"
import { TraitExpression } from "./TraitExpression"
export function spreadSupertraits<
const T extends readonly Trait<
TraitExpression<
typeof TraitExpression.NullSuperclass,
readonly Trait<any, any, any, any>[]
>,
any,
any,
any
>[]
>(
traits: T
) {
return traits.flatMap(trait => [
...trait.superExpression.traits,
trait,
]) as readonly Trait<any, any, any, any>[] as SpreadSupertraits<T>
}
export type SpreadSupertraits<Traits> = (
Traits extends readonly [
infer El extends Trait<any, any, any, any>,
...infer Rest,
]
? readonly [
...Trait.Supertraits<El>,
El,
...SpreadSupertraits<Rest>,
]
: readonly []
)

39
src/traitsUnique.ts Normal file
View File

@@ -0,0 +1,39 @@
import { unique } from "remeda"
import { IsEqual } from "type-fest"
import { Trait } from "./Trait"
import { TraitExpression } from "./TraitExpression"
export function traitsUnique<
const T extends readonly Trait<
TraitExpression<
typeof TraitExpression.NullSuperclass,
readonly Trait<any, any, any, any>[]
>,
any,
any,
any
>[]
>(
traits: T
) {
return unique(traits) as readonly Trait<any, any, any, any>[] as TraitsUnique<T>
}
export type TraitsUnique<Traits> = (
Traits extends readonly [
...infer Rest,
infer El extends Trait<any, any, any, any>,
]
? IsTraitInTupleFromRight<Rest, El> extends true
? TraitsUnique<Rest>
: readonly [...TraitsUnique<Rest>, El]
: readonly []
)
type IsTraitInTupleFromRight<Traits, T> = (
Traits extends readonly [...infer Rest, infer El]
? IsEqual<El, T> extends true
? true
: IsTraitInTupleFromRight<Rest, T>
: false
)