0.1.21 #21

Merged
Thilawyn merged 23 commits from next into master 2024-05-12 01:11:51 +02:00
4 changed files with 166 additions and 82 deletions
Showing only changes of commit 90bb907db2 - Show all commits

View File

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