From 175864950739a74d9ff187253d9f9bd5620cb902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 14 Feb 2024 21:13:02 +0100 Subject: [PATCH] Complete refactoring --- src/Trait.ts | 73 +++++++++------------------------ src/TraitBuilder.ts | 4 +- src/TraitExpression.ts | 59 ++++++++++++--------------- src/TraitExpressionBuilder.ts | 76 +++++++++++++++-------------------- 4 files changed, 77 insertions(+), 135 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 350c818..fbc5f90 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -1,17 +1,13 @@ import { Fn, Pipe, Tuples } from "hotscript" -import { AbstractClass, Class, Opaque } from "type-fest" -import { TraitExpression, emptyTraitExpression } from "./TraitExpression" -import { AbstractTag } from "./abstract" +import { AbstractClass, Class } from "type-fest" +import { TraitExpression } from "./TraitExpression" import { ExtendFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" -export type TraitApplierSuperTag = "@thilawyn/traitify-ts/Super" - - export type AddAbstractToImplClass< - ImplClass extends Class<{}, []>, - Abstract extends {}, - StaticAbstract extends {}, + ImplClass extends Class, + Abstract extends object, + StaticAbstract extends object, > = ( Class< Abstract & @@ -23,45 +19,32 @@ export type AddAbstractToImplClass< StaticMembers ) -export type RemoveAbstractFromImplClass< - ImplClassWithAbstract extends Class & StaticAbstract & { _tag: TraitApplierSuperTag }, - Abstract extends {}, - StaticAbstract extends {}, -> = ( - Class< - Omit, keyof Abstract>, - ConstructorParameters - > & - Omit, keyof StaticAbstract | "_tag"> -) - export class Trait< - Supertraits extends TraitExpression< + SuperExpression extends TraitExpression< typeof TraitExpression.NullSuperclass, - Trait[], Trait[] >, - Abstract extends {}, - StaticAbstract extends {}, - ImplClass extends Class<{}, []>, + Abstract extends object, + StaticAbstract extends object, + ImplClass extends Class, > { constructor( - readonly supertraits: Supertraits, - readonly abstract: Abstract, - readonly staticAbstract: StaticAbstract, - readonly apply: (Super: AbstractClass<{}>) => ImplClass, + readonly superExpression: SuperExpression, + readonly abstract: Abstract, + readonly staticAbstract: StaticAbstract, + readonly apply: (Super: AbstractClass) => ImplClass, ) {} } export namespace Trait { - export type OwnSupertraits = ( - T extends Trait - ? Supertraits + export type OwnSuperExpression = ( + T extends Trait + ? SuperExpression : never ) - export interface OwnSupertraitsFn extends Fn { - return: Trait.OwnSupertraits + export interface OwnSuperExpressionFn extends Fn { + return: Trait.OwnSuperExpression } export type OwnAbstract = ( @@ -113,7 +96,7 @@ export namespace Trait { } export type Supertraits = ( - TraitExpression.AllTraits> + TraitExpression.Traits> ) export interface SupertraitsFn extends Fn { return: Trait.Supertraits @@ -150,21 +133,3 @@ export namespace Trait { return: Trait.Instance } } - - -export function trait< - Abstract extends {}, - StaticAbstract extends {}, - ImplClassWithAbstract extends Class & StaticAbstract & { _tag: TraitApplierSuperTag }, ->( - abstract: Opaque, - staticAbstract: Opaque, - apply: (Super: AbstractClass & StaticAbstract & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract, -) { - return new Trait( - emptyTraitExpression, - abstract as Abstract, - staticAbstract as StaticAbstract, - apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, - ) -} diff --git a/src/TraitBuilder.ts b/src/TraitBuilder.ts index c40a5fa..6c43e8b 100644 --- a/src/TraitBuilder.ts +++ b/src/TraitBuilder.ts @@ -26,7 +26,6 @@ export type RemoveAbstractFromImplClass< export class TraitBuilder< SuperExpression extends TraitExpression< typeof TraitExpression.NullSuperclass, - Trait[], Trait[] >, Abstract extends object, @@ -91,9 +90,8 @@ export class TraitBuilder< } } - export const trait = new TraitBuilder( - new TraitExpression(TraitExpression.NullSuperclass, [], []), + new TraitExpression(TraitExpression.NullSuperclass, []), {}, {}, Super => class extends Super {}, diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 188edc0..9b65e06 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,7 +1,7 @@ import { Fn, Pipe, Tuples } from "hotscript" -import { AbstractClass, Class, Opaque } from "type-fest" -import { RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "./Trait" -import { AbstractTag } from "./abstract" +import { AbstractClass } from "type-fest" +import { Trait } from "./Trait" +import { TraitBuilder } from "./TraitBuilder" import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" @@ -13,19 +13,17 @@ import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpression< - Superclass extends AbstractClass<{}>, - const OwnTraits extends Trait[], - const AllTraits extends Trait[], + Superclass extends AbstractClass, + const Traits extends Trait[], > { constructor( readonly superclass: Superclass, - readonly ownTraits: OwnTraits, - readonly allTraits: AllTraits, + readonly traits: Traits, ) {} get extends(): ( AbstractClass< - Pipe, // Map all the traits to the instance of their implementation class Tuples.Prepend>, // Add the instance of the superclass at the top of the list ExtendFn, // Reduce to a single instance that extends all the instances in the list @@ -35,7 +33,7 @@ export class TraitExpression< ConstructorParameters > & - Pipe, // Map all the traits to their implementation class Tuples.Prepend, // Add the superclass at the top of the list Tuples.Map, // Map all the classes to an object containing their static members @@ -43,7 +41,7 @@ export class TraitExpression< SimplifyFn, // Make readable for IDEs ]> ) { - return this.allTraits.reduce( + return this.traits.reduce( (previous, trait) => trait.apply(previous), this.superclass, ) as any @@ -52,11 +50,15 @@ export class TraitExpression< implementsStatic(target: ImplementsStatic, context: any) {} subtrait< - This extends TraitExpression + This extends TraitExpression >( this: This ) { - return new Trait( + return new TraitBuilder( + this, + {}, + {}, + Super => class extends Super {}, ) } } @@ -67,7 +69,7 @@ export namespace TraitExpression { } export type Superclass = ( - T extends TraitExpression + T extends TraitExpression ? Superclass : never ) @@ -75,40 +77,29 @@ export namespace TraitExpression { return: TraitExpression.Superclass } - export type OwnTraits = ( - T extends TraitExpression - ? OwnTraits + export type Traits = ( + T extends TraitExpression + ? Traits : never ) - export interface OwnTraitsFn extends Fn { - return: TraitExpression.OwnTraits - } - - export type AllTraits = ( - T extends TraitExpression - ? AllTraits - : never - ) - export interface AllTraitsFn extends Fn { - return: TraitExpression.AllTraits + export interface TraitsFn extends Fn { + return: TraitExpression.Traits } } -export const emptyTraitExpression = new TraitExpression(TraitExpression.NullSuperclass, [], []) - -export type Implements> = ( +export type Implements> = ( Pipe, ExtendFn, SimplifyFn, ]> ) -export type ImplementsStatic> = ( +export type ImplementsStatic> = ( Pipe, ExtendFn, SimplifyFn, diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index 8e5c85e..23c76de 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -2,7 +2,7 @@ import { Call, Fn, Pipe, Tuples } from "hotscript" import { uniq } from "lodash-es" import { AbstractClass } from "type-fest" import { Trait } from "./Trait" -import { TraitExpression, emptyTraitExpression } from "./TraitExpression" +import { TraitExpression } from "./TraitExpression" import { ExtendableFn, StaticMembersFn } from "./util" @@ -51,76 +51,64 @@ type ImplStaticMembersExtendable< type BuildTraitExpression< Superclass extends AbstractClass<{}>, - OwnTraits extends Trait[], - AllTraits extends Trait[], + Traits extends Trait[], > = ( - AbstractMembersExtendable extends false + AbstractMembersExtendable extends false ? "Type conflict between the traits abstract members and/or the superclass instance." - : ImplInstanceExtendable extends false + : ImplInstanceExtendable extends false ? "Type conflict between the traits implementation instances and/or the superclass instance." - : ImplStaticMembersExtendable extends false + : ImplStaticMembersExtendable extends false ? "Type conflict between the traits implementation static members and/or the superclass static members." - : TraitExpression + : TraitExpression ) class TraitExpressionBuilder< - Superclass extends AbstractClass<{}>, - const OwnTraits extends Trait[], - const AllTraits extends Trait[], + Superclass extends AbstractClass, + const Traits extends Trait[], > { - constructor(private readonly expression: TraitExpression) {} + constructor( + private readonly expressionSuperclass: Superclass, + private readonly expressionTraits: Traits, + ) {} extends< - Super extends AbstractClass + Super extends AbstractClass >( superclass: Super ) { return new TraitExpressionBuilder( - new TraitExpression( - superclass, - this.expression.ownTraits, - this.expression.allTraits, - ) + superclass, + this.expressionTraits, ) } expresses< - const Traits extends Trait[] + const T extends Trait[] >( - ...traits: Traits + ...traits: T ): TraitExpressionBuilder< Superclass, - [...OwnTraits, ...Traits], - [...AllTraits, ...SpreadSupertraits] + [...Traits, ...SpreadSupertraits] > { return new TraitExpressionBuilder( - new TraitExpression( - this.expression.superclass, - uniq([...this.expression.ownTraits, ...traits]) as [...OwnTraits, ...Traits], - uniq([...this.expression.allTraits, ...this.spreadSupertraits(traits)]) as [...AllTraits, ...SpreadSupertraits], - ) + this.expressionSuperclass, + + uniq([ + ...this.expressionTraits, + ...traits.flatMap(trait => [ + ...trait.superExpression.allTraits, + trait, + ]), + ]) as [...Traits, ...SpreadSupertraits], ) } - private spreadSupertraits< - const Traits extends Trait< - TraitExpression[]>, - any, - any, - any - >[] - >( - traits: Traits - ) { - return traits.flatMap(trait => [ - ...trait.supertraits.allTraits, - trait, - ]) as SpreadSupertraits - } - build() { - return this.expression as BuildTraitExpression + return new TraitExpression( + this.expressionSuperclass, + this.expressionTraits, + ) as BuildTraitExpression } then(fn: (expression: ReturnType) => V): V { @@ -128,4 +116,4 @@ class TraitExpressionBuilder< } } -export const expression = new TraitExpressionBuilder(emptyTraitExpression) +export const expression = new TraitExpressionBuilder(TraitExpression.NullSuperclass, [])