Files
traitify-ts/src/TraitBuilder.ts
Julien Valverdé 34c91707ae
All checks were successful
continuous-integration/drone/push Build is passing
TraitExpression work
2024-02-19 01:11:22 +01:00

124 lines
3.4 KiB
TypeScript

import { AbstractClass, Simplify } from "type-fest"
import { Trait, Traits } from "./Trait"
import { TraitExpression } from "./TraitExpression"
import { ExtendPlain, StaticMembers } from "./util"
type ImplSuper<
SuperExpression extends TraitExpression<
typeof TraitExpression.NullSuperclass,
Trait<any, any, any, any>[]
>,
Abstract extends object,
StaticAbstract extends object,
> = (
AbstractClass<
ExtendPlain<[
...Traits.MapImplInstance<
TraitExpression.Traits<SuperExpression>
>,
Abstract,
]>
> &
ExtendPlain<[
...Traits.MapImplStaticMembers<
TraitExpression.Traits<SuperExpression>
>,
StaticAbstract,
]> &
{ readonly _tag: "@thilawyn/traitify-ts/Super" } // TODO: replace with unique symbol?
)
export class TraitBuilder<
SuperExpression extends TraitExpression<
typeof TraitExpression.NullSuperclass,
Trait<any, any, any, any>[]
>,
Abstract extends object,
StaticAbstract extends object,
ImplClass extends AbstractClass<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>(
_: (Super: AbstractClass<Abstract>) => AbstractClass<A, []>
) {
return new TraitBuilder(
this.traitSuperExpression,
{} as Simplify<A>,
this.traitStaticAbstract,
this.traitApply,
)
}
staticAbstract<A extends StaticAbstract>(
_: (Super: AbstractClass<StaticAbstract>) => AbstractClass<A, []>
) {
return new TraitBuilder(
this.traitSuperExpression,
this.traitAbstract,
{} as Simplify<A>,
this.traitApply,
)
}
implement<
ImplClassWithAbstract extends ImplSuper< // TODO: use This instead?
SuperExpression,
Abstract,
StaticAbstract
>
>(
apply: (
Super: ImplSuper<SuperExpression, Abstract, StaticAbstract>
) => ImplClassWithAbstract
) {
return new TraitBuilder(
this.traitSuperExpression,
this.traitAbstract,
this.traitStaticAbstract,
apply as unknown as (Super: AbstractClass<object>) => (
AbstractClass<
Simplify<
Omit<
InstanceType<ImplClassWithAbstract>,
keyof Abstract
>
>,
ConstructorParameters<ImplClassWithAbstract>
> &
Simplify<
Omit<
StaticMembers<ImplClassWithAbstract>,
keyof StaticAbstract | "_tag"
>
>
),
)
}
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 {},
)