110 lines
2.8 KiB
TypeScript
110 lines
2.8 KiB
TypeScript
import { Call, Fn, Pipe, Tuples } from "hotscript"
|
|
import { AbstractClass, Class, Opaque } from "type-fest"
|
|
import { AbstractTag, Trait, TraitApplierSuperTag } from "."
|
|
import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util"
|
|
|
|
|
|
export class TraitExpressionNullSuperclass {}
|
|
|
|
export class TraitExpression<
|
|
Superclass extends AbstractClass<{}>,
|
|
OwnTraits extends Trait<any, any, any>[],
|
|
AllTraits extends Trait<any, any, any>[],
|
|
> {
|
|
constructor(
|
|
readonly superclass: Superclass,
|
|
readonly ownTraits: OwnTraits,
|
|
readonly allTraits: AllTraits,
|
|
) {}
|
|
|
|
get extends(): (
|
|
AbstractClass<
|
|
Pipe<[
|
|
InstanceType<Superclass>,
|
|
...Call<Tuples.Map<Trait.OwnImplInstanceFn>, OwnTraits>,
|
|
], [
|
|
ExtendFn,
|
|
SimplifyFn,
|
|
]>,
|
|
|
|
ConstructorParameters<Superclass>
|
|
> &
|
|
|
|
Pipe<[
|
|
Superclass,
|
|
...Call<Tuples.Map<Trait.OwnImplClassFn>, OwnTraits>,
|
|
], [
|
|
Tuples.Map<StaticMembersFn>,
|
|
ExtendFn,
|
|
SimplifyFn,
|
|
]>
|
|
) {
|
|
return this.allTraits.reduce(
|
|
(previous, trait) => trait.apply(previous),
|
|
this.superclass as Opaque<Superclass, TraitApplierSuperTag>,
|
|
) as any
|
|
}
|
|
|
|
subtrait<
|
|
SubtraitAbstract extends {},
|
|
SubtraitImplWithAbstract extends Class<{}>,
|
|
>(
|
|
abstract: (
|
|
abstract: Pipe<typeof this, [
|
|
|
|
]>
|
|
) => Opaque<SubtraitAbstract, AbstractTag>,
|
|
|
|
// impl: ()
|
|
) {
|
|
|
|
}
|
|
}
|
|
|
|
export namespace TraitExpression {
|
|
export type Superclass<T> = (
|
|
T extends TraitExpression<infer Superclass, any, any>
|
|
? Superclass
|
|
: never
|
|
)
|
|
export interface SuperclassFn extends Fn {
|
|
return: TraitExpression.Superclass<this["arg0"]>
|
|
}
|
|
|
|
export type OwnTraits<T> = (
|
|
T extends TraitExpression<any, infer OwnTraits, any>
|
|
? OwnTraits
|
|
: never
|
|
)
|
|
export interface OwnTraitsFn extends Fn {
|
|
return: TraitExpression.OwnTraits<this["arg0"]>
|
|
}
|
|
|
|
export type AllTraits<T> = (
|
|
T extends TraitExpression<any, any, infer AllTraits>
|
|
? AllTraits
|
|
: never
|
|
)
|
|
export interface AllTraitsFn extends Fn {
|
|
return: TraitExpression.AllTraits<this["arg0"]>
|
|
}
|
|
}
|
|
|
|
|
|
export type Implements<Exp extends TraitExpression<any, any, any>> = (
|
|
Exp extends TraitExpression<any, infer AllTraits, any>
|
|
? Pipe<AllTraits, [
|
|
Tuples.Map<Trait.OwnAbstractFn>,
|
|
ExtendFn,
|
|
SimplifyFn,
|
|
]>
|
|
: never
|
|
)
|
|
|
|
|
|
export const emptyTraitExpression = new TraitExpression(
|
|
TraitExpressionNullSuperclass,
|
|
[] as const,
|
|
[] as const,
|
|
)
|