diff --git a/src/Trait.ts b/src/Trait.ts index 1612d03..350c818 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -5,7 +5,7 @@ import { AbstractTag } from "./abstract" import { ExtendFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" -export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" +export type TraitApplierSuperTag = "@thilawyn/traitify-ts/Super" export type AddAbstractToImplClass< diff --git a/src/TraitBuilder.ts b/src/TraitBuilder.ts index 47579c2..e782495 100644 --- a/src/TraitBuilder.ts +++ b/src/TraitBuilder.ts @@ -1,21 +1,100 @@ -import { Class } from "type-fest" +import { AbstractClass, Class } from "type-fest" import { Trait } from "./Trait" import { TraitExpression } from "./TraitExpression" +import { StaticMembers } from "./util" -/* - Ideas: - - Make .abstract() and .staticAbstract() merge the declaration with the current Abstract or StaticAbstract -*/ -class TraitBuilder< - Supertraits extends TraitExpression< +export type TraitApplierSuperTag = "@thilawyn/traitify-ts/Super" + +export type RemoveAbstractFromImplClass< + ImplClassWithAbstract extends ( + Class & + StaticAbstract & + { _tag: TraitApplierSuperTag } + ), + Abstract extends object, + StaticAbstract extends object, +> = ( + Class< + Omit, keyof Abstract>, + ConstructorParameters + > & + Omit, keyof StaticAbstract | "_tag"> +) + + +export class TraitBuilder< + 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( + private readonly traitSuperExpression: SuperExpression, + private readonly traitAbstract: Abstract, + private readonly traitStaticAbstract: StaticAbstract, + private readonly traitApply: (Super: AbstractClass) => ImplClass, + ) {} + abstract() { + return new TraitBuilder( + this.traitSuperExpression, + {} as A, + this.traitStaticAbstract, + this.traitApply, + ) + } + + staticAbstract() { + return new TraitBuilder( + this.traitSuperExpression, + this.traitAbstract, + {} as A, + this.traitApply, + ) + } + + implement< + ImplClassWithAbstract extends ( + Class & + StaticAbstract & + { _tag: TraitApplierSuperTag } + ) + >( + apply: ( + Super: ( + AbstractClass & + StaticAbstract & + { _tag: TraitApplierSuperTag } + ) + ) => ImplClassWithAbstract + ) { + return new Trait( + this.traitSuperExpression, + this.traitAbstract, + this.traitStaticAbstract, + apply as unknown as (Super: AbstractClass) => RemoveAbstractFromImplClass, + ) + } + + build() { + return new Trait( + this.traitSuperExpression, + this.traitAbstract, + this.traitStaticAbstract, + this.traitApply, + ) + } } + + +export const trait = new TraitBuilder( + new TraitExpression(TraitExpression.NullSuperclass, [], []), + {}, + {}, + Super => class extends Super {}, +) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index 0e9ed0d..8e5c85e 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -69,7 +69,7 @@ class TraitExpressionBuilder< const OwnTraits extends Trait[], const AllTraits extends Trait[], > { - constructor(private expression: TraitExpression) {} + constructor(private readonly expression: TraitExpression) {} extends< Super extends AbstractClass