Files
traitify-ts/src/TraitBuilder.ts
Julien Valverdé 1758649507
Some checks failed
continuous-integration/drone/push Build is failing
Complete refactoring
2024-02-14 21:13:02 +01:00

99 lines
2.7 KiB
TypeScript

import { AbstractClass, Class } from "type-fest"
import { Trait } from "./Trait"
import { TraitExpression } from "./TraitExpression"
import { StaticMembers } from "./util"
export type TraitApplierSuperTag = "@thilawyn/traitify-ts/Super"
export type RemoveAbstractFromImplClass<
ImplClassWithAbstract extends (
Class<Abstract, []> &
StaticAbstract &
{ _tag: TraitApplierSuperTag }
),
Abstract extends object,
StaticAbstract extends object,
> = (
Class<
Omit<InstanceType<ImplClassWithAbstract>, keyof Abstract>,
ConstructorParameters<ImplClassWithAbstract>
> &
Omit<StaticMembers<ImplClassWithAbstract>, keyof StaticAbstract | "_tag">
)
export class TraitBuilder<
SuperExpression extends TraitExpression<
typeof TraitExpression.NullSuperclass,
Trait<any, any, any, any>[]
>,
Abstract extends object,
StaticAbstract extends object,
ImplClass extends Class<object, []>,
> {
constructor(
private readonly traitSuperExpression: SuperExpression,
private readonly traitAbstract: Abstract,
private readonly traitStaticAbstract: StaticAbstract,
private readonly traitApply: (Super: AbstractClass<object>) => ImplClass,
) {}
abstract<A extends Abstract>() {
return new TraitBuilder(
this.traitSuperExpression,
{} as A,
this.traitStaticAbstract,
this.traitApply,
)
}
staticAbstract<A extends StaticAbstract>() {
return new TraitBuilder(
this.traitSuperExpression,
this.traitAbstract,
{} as A,
this.traitApply,
)
}
implement<
ImplClassWithAbstract extends (
Class<Abstract, []> &
StaticAbstract &
{ _tag: TraitApplierSuperTag }
)
>(
apply: (
Super: (
AbstractClass<Abstract> &
StaticAbstract &
{ _tag: TraitApplierSuperTag }
)
) => ImplClassWithAbstract
) {
return new TraitBuilder(
this.traitSuperExpression,
this.traitAbstract,
this.traitStaticAbstract,
apply as unknown as (Super: AbstractClass<object>) => RemoveAbstractFromImplClass<ImplClassWithAbstract, Abstract, StaticAbstract>,
)
}
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 {},
)