Files
traitify-ts/src/TraitBuilder.ts
Julien Valverdé 15c5548fde
All checks were successful
continuous-integration/drone/push Build is passing
Fixed TraitBuilder
2024-02-17 03:31:46 +01:00

160 lines
4.5 KiB
TypeScript

import { Pipe, Tuples } from "hotscript"
import { AbstractClass, Class } from "type-fest"
import { Trait, TraitClass, TraitConcreteClass } from "./Trait"
import { TraitExpression } from "./TraitExpression"
import { ExtendFn, SimplifyFn, StaticMembers } from "./util"
type ExtendAbstractSuper<SuperExpression, Abstract> = (
Pipe<SuperExpression, [
TraitExpression.TraitsFn,
Tuples.Map<Trait.OwnAbstractFn>,
Tuples.Append<Abstract>,
ExtendFn,
SimplifyFn,
]>
)
type ExtendStaticAbstractSuper<SuperExpression, StaticAbstract> = (
Pipe<SuperExpression, [
TraitExpression.TraitsFn,
Tuples.Map<Trait.OwnStaticAbstractFn>,
Tuples.Append<StaticAbstract>,
ExtendFn,
SimplifyFn,
]>
)
type TraitApplierSuperTag = "@thilawyn/traitify-ts/Super"
type RemoveAbstractFromImplClass<
ImplClassWithAbstract extends AbstractClass<object>,
Abstract extends AbstractClass<object>,
> = (
Class<
Omit<
InstanceType<ImplClassWithAbstract>,
keyof InstanceType<Abstract>
>,
ConstructorParameters<ImplClassWithAbstract>
> &
Omit<
StaticMembers<ImplClassWithAbstract>,
keyof StaticMembers<Abstract> | "_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 ExtendAbstractSuper<SuperExpression, Abstract>>() {
return new TraitBuilder(
this.traitSuperExpression,
{} as A,
this.traitStaticAbstract,
this.traitApply,
)
}
extendAbstract<A extends ExtendAbstractSuper<SuperExpression, Abstract>>(
_: (
Super: AbstractClass<
ExtendAbstractSuper<SuperExpression, Abstract>
>
) => AbstractClass<A, []>
) {
return new TraitBuilder(
this.traitSuperExpression,
{} as A,
this.traitStaticAbstract,
this.traitApply,
)
}
staticAbstract<A extends ExtendStaticAbstractSuper<SuperExpression, StaticAbstract>>() {
return new TraitBuilder(
this.traitSuperExpression,
this.traitAbstract,
{} as A,
this.traitApply,
)
}
extendStaticAbstract<A extends ExtendStaticAbstractSuper<SuperExpression, StaticAbstract>>(
_: (
Super: AbstractClass<
ExtendStaticAbstractSuper<SuperExpression, StaticAbstract>
>
) => AbstractClass<A, []>
) {
return new TraitBuilder(
this.traitSuperExpression,
this.traitAbstract,
{} as A,
this.traitApply,
)
}
implement<
ImplClassWithAbstract extends (
TraitConcreteClass<
Trait<SuperExpression, Abstract, StaticAbstract, ImplClass>
> &
{ _tag: TraitApplierSuperTag }
)
>(
apply: (
Super: (
TraitClass<
Trait<SuperExpression, Abstract, StaticAbstract, ImplClass>
> &
{ _tag: TraitApplierSuperTag }
)
) => ImplClassWithAbstract
) {
return new TraitBuilder(
this.traitSuperExpression,
this.traitAbstract,
this.traitStaticAbstract,
apply as unknown as (Super: AbstractClass<object>) => RemoveAbstractFromImplClass<
ImplClassWithAbstract,
TraitClass<
Trait<SuperExpression, Abstract, StaticAbstract, ImplClass>
>
>,
)
}
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 {},
)