diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index c563268..464740d 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -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, const Traits extends readonly Trait[], > { - 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 - >[] - >( - traits: T - ) { - return traits.flatMap(trait => [ - ...trait.superExpression.traits, - trait, - ]) as readonly Trait[] as TraitExpressionBuilder.SpreadSupertraits - } - - static traitsUnique< - const T extends readonly Trait< - TraitExpression< - typeof TraitExpression.NullSuperclass, - readonly Trait[] - >, - any, - any, - any - >[] - >( - traits: T - ) { - return unique(traits) as readonly Trait[] as TraitExpressionBuilder.TraitsUnique - } - - extends< Super extends AbstractClass >( superclass: Super ) { - return new this.constructor( + return new TraitExpressionBuilder( superclass, this.expressionTraits, ) @@ -80,12 +43,12 @@ export class TraitExpressionBuilder< Superclass, TraitExpressionBuilder.ExpressesReturnTypeTraits > { - 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 > { - 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 extends readonly [ - infer El extends Trait, - ...infer Rest, - ] - ? readonly [ - ...Trait.Supertraits, - El, - ...SpreadSupertraits, - ] - : readonly [] - ) - - export type TraitsUnique = ( - Traits extends readonly [ - ...infer Rest, - infer El extends Trait, - ] - ? IsTraitInTupleFromRight extends true - ? TraitsUnique - : readonly [...TraitsUnique, El] - : readonly [] - ) - type IsTraitInTupleFromRight = ( - Traits extends readonly [...infer Rest, infer El] - ? IsEqual extends true - ? true - : IsTraitInTupleFromRight - : false - ) - export type ExpressesReturnTypeTraits< Traits extends readonly Trait[], T extends readonly Trait[], > = ( - TraitExpressionBuilder.TraitsUnique, + ...SpreadSupertraits, ]> ) @@ -186,8 +118,8 @@ export namespace TraitExpressionBuilder { Traits extends readonly Trait[], T extends readonly Trait[], > = ( - TraitExpressionBuilder.TraitsUnique, + TraitsUnique, ...Traits, ]> ) diff --git a/src/effect/EffectSchemaTraitExpressionBuilder.ts b/src/effect/EffectSchemaTraitExpressionBuilder.ts new file mode 100644 index 0000000..a67c018 --- /dev/null +++ b/src/effect/EffectSchemaTraitExpressionBuilder.ts @@ -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, + const Traits extends readonly Trait[], + + 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, + + SuperFields extends S.Struct.Fields, + SuperA, SuperI, SuperR, SuperC, + SuperInherited extends object, + SuperProto, + >( + superclass: Super | S.Class + ) { + 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 + >[] + >( + ...traits: T + ): EffectSchemaTraitExpressionBuilder< + Superclass, + TraitExpressionBuilder.ExpressesReturnTypeTraits, + + Fields, + A, I, R, C, + Inherited, + Proto + > { + return new EffectSchemaTraitExpressionBuilder( + this.expressionSuperclass, + + traitsUnique([ + ...this.expressionTraits, + ...spreadSupertraits(traits), + ]), + ) + } +} diff --git a/src/spreadSupertraits.ts b/src/spreadSupertraits.ts new file mode 100644 index 0000000..77c3377 --- /dev/null +++ b/src/spreadSupertraits.ts @@ -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 + >[] +>( + traits: T +) { + return traits.flatMap(trait => [ + ...trait.superExpression.traits, + trait, + ]) as readonly Trait[] as SpreadSupertraits +} + +export type SpreadSupertraits = ( + Traits extends readonly [ + infer El extends Trait, + ...infer Rest, + ] + ? readonly [ + ...Trait.Supertraits, + El, + ...SpreadSupertraits, + ] + : readonly [] +) diff --git a/src/traitsUnique.ts b/src/traitsUnique.ts new file mode 100644 index 0000000..6df91cd --- /dev/null +++ b/src/traitsUnique.ts @@ -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 + >[] +>( + traits: T +) { + return unique(traits) as readonly Trait[] as TraitsUnique +} + +export type TraitsUnique = ( + Traits extends readonly [ + ...infer Rest, + infer El extends Trait, + ] + ? IsTraitInTupleFromRight extends true + ? TraitsUnique + : readonly [...TraitsUnique, El] + : readonly [] +) +type IsTraitInTupleFromRight = ( + Traits extends readonly [...infer Rest, infer El] + ? IsEqual extends true + ? true + : IsTraitInTupleFromRight + : false +)