0.1.11 #11
@@ -6,7 +6,91 @@ import { Extend, StaticMembers } from "./util"
|
|||||||
|
|
||||||
declare const implSuperSymbol: unique symbol
|
declare const implSuperSymbol: unique symbol
|
||||||
|
|
||||||
type ImplSuper<This> = (
|
|
||||||
|
export class TraitBuilder<
|
||||||
|
SuperExpression extends TraitExpression<
|
||||||
|
typeof TraitExpression.NullSuperclass,
|
||||||
|
Trait<any, any, any, any>[]
|
||||||
|
>,
|
||||||
|
Abstract extends object,
|
||||||
|
StaticAbstract extends object,
|
||||||
|
ImplClass extends AbstractClass<object, []>,
|
||||||
|
> {
|
||||||
|
declare ["constructor"]: typeof TraitBuilder
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly traitSuperExpression: SuperExpression,
|
||||||
|
readonly traitAbstract: Abstract,
|
||||||
|
readonly traitStaticAbstract: StaticAbstract,
|
||||||
|
readonly traitApply: (Super: AbstractClass<object>) => ImplClass,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
|
||||||
|
abstract<A extends Abstract>(
|
||||||
|
_: (Super: AbstractClass<Abstract>) => AbstractClass<A, []>
|
||||||
|
) {
|
||||||
|
return new this.constructor(
|
||||||
|
this.traitSuperExpression,
|
||||||
|
{} as Simplify<A>,
|
||||||
|
this.traitStaticAbstract,
|
||||||
|
this.traitApply,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
staticAbstract<A extends StaticAbstract>(
|
||||||
|
_: (Super: AbstractClass<StaticAbstract>) => AbstractClass<A, []>
|
||||||
|
) {
|
||||||
|
return new this.constructor(
|
||||||
|
this.traitSuperExpression,
|
||||||
|
this.traitAbstract,
|
||||||
|
{} as Simplify<A>,
|
||||||
|
this.traitApply,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
implement<
|
||||||
|
ImplClassWithAbstract extends TraitBuilder.ImplSuper<typeof this> // TODO: find a way to set the constraint to concrete classes while keeping the Super arg as an abstract class
|
||||||
|
>(
|
||||||
|
apply: (Super: TraitBuilder.ImplSuper<typeof this>) => ImplClassWithAbstract
|
||||||
|
) {
|
||||||
|
return new this.constructor(
|
||||||
|
this.traitSuperExpression,
|
||||||
|
this.traitAbstract,
|
||||||
|
this.traitStaticAbstract,
|
||||||
|
|
||||||
|
apply as unknown as (Super: AbstractClass<object>) => (
|
||||||
|
AbstractClass<
|
||||||
|
Simplify<
|
||||||
|
Omit<
|
||||||
|
InstanceType<ImplClassWithAbstract>,
|
||||||
|
keyof Abstract
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> &
|
||||||
|
|
||||||
|
Simplify<
|
||||||
|
Omit<
|
||||||
|
StaticMembers<ImplClassWithAbstract>,
|
||||||
|
keyof StaticAbstract | typeof implSuperSymbol
|
||||||
|
>
|
||||||
|
>
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
build() {
|
||||||
|
return new Trait(
|
||||||
|
this.traitSuperExpression,
|
||||||
|
this.traitAbstract,
|
||||||
|
this.traitStaticAbstract,
|
||||||
|
this.traitApply,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace TraitBuilder {
|
||||||
|
export type ImplSuper<This> = (
|
||||||
This extends TraitBuilder<
|
This extends TraitBuilder<
|
||||||
any,
|
any,
|
||||||
infer Abstract,
|
infer Abstract,
|
||||||
@@ -33,85 +117,8 @@ type ImplSuper<This> = (
|
|||||||
)
|
)
|
||||||
: never
|
: never
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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(
|
|
||||||
readonly traitSuperExpression: SuperExpression,
|
|
||||||
readonly traitAbstract: Abstract,
|
|
||||||
readonly traitStaticAbstract: StaticAbstract,
|
|
||||||
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<typeof this> // TODO: find a way to set the constraint to concrete classes while keeping the Super arg as an abstract class
|
|
||||||
>(
|
|
||||||
apply: (Super: ImplSuper<typeof this>) => ImplClassWithAbstract
|
|
||||||
) {
|
|
||||||
return new TraitBuilder(
|
|
||||||
this.traitSuperExpression,
|
|
||||||
this.traitAbstract,
|
|
||||||
this.traitStaticAbstract,
|
|
||||||
|
|
||||||
apply as unknown as (Super: AbstractClass<object>) => (
|
|
||||||
AbstractClass<
|
|
||||||
Simplify<
|
|
||||||
Omit<
|
|
||||||
InstanceType<ImplClassWithAbstract>,
|
|
||||||
keyof Abstract
|
|
||||||
>
|
|
||||||
>
|
|
||||||
> &
|
|
||||||
|
|
||||||
Simplify<
|
|
||||||
Omit<
|
|
||||||
StaticMembers<ImplClassWithAbstract>,
|
|
||||||
keyof StaticAbstract | typeof implSuperSymbol
|
|
||||||
>
|
|
||||||
>
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
return new Trait(
|
|
||||||
this.traitSuperExpression,
|
|
||||||
this.traitAbstract,
|
|
||||||
this.traitStaticAbstract,
|
|
||||||
this.traitApply,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const trait = new TraitBuilder(
|
export const trait = new TraitBuilder(
|
||||||
new TraitExpression(TraitExpression.NullSuperclass, []),
|
new TraitExpression(TraitExpression.NullSuperclass, []),
|
||||||
|
|||||||
Reference in New Issue
Block a user