0.1.0 (#1)
All checks were successful
continuous-integration/drone/push Build is passing

Co-authored-by: Julien Valverdé <julien.valverde@mailo.com>
Reviewed-on: https://git.jvalver.de/Thilawyn/traitify-ts/pulls/1
This commit was merged in pull request #1.
This commit is contained in:
Julien Valverdé
2024-02-06 03:15:39 +01:00
parent eaaabeec49
commit 65092c27cb
19 changed files with 582 additions and 423 deletions

117
src/TraitExpression.ts Normal file
View File

@@ -0,0 +1,117 @@
import { Call, Fn, Pipe, Tuples } from "hotscript"
import { AbstractClass, Class, Opaque } from "type-fest"
import { AbstractTag, RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "."
import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util"
// type RemoveSupertraitsAbstractFromAbstract<Left, Right> = {
// [Key in Extract<keyof Left, keyof Right>]: Left[Key]
// } & {
// [Key in Exclude<keyof Left, keyof Right>]: Left[Key]
// }
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>, AllTraits>,
], [
ExtendFn,
SimplifyFn,
]>,
ConstructorParameters<Superclass>
> &
Pipe<[
Superclass,
...Call<Tuples.Map<Trait.OwnImplClassFn>, AllTraits>,
], [
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 Implements<typeof this>,
SubtraitImplClassWithAbstract extends Class<SubtraitAbstract, []>,
>(
abstract: (expression: typeof this) => Opaque<SubtraitAbstract, AbstractTag>,
apply: (Super: Opaque<AbstractClass<SubtraitAbstract>, TraitApplierSuperTag>) => (
Opaque<SubtraitImplClassWithAbstract, TraitApplierSuperTag>
),
) {
return new Trait(
this,
// {} as RemoveSupertraitsAbstractFromAbstract<SubtraitAbstract, Implements<typeof this>>,
{} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements<typeof this> from this.
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<SubtraitImplClassWithAbstract, SubtraitAbstract>,
)
}
}
export namespace TraitExpression {
export class NullSuperclass {}
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 const emptyTraitExpression = new TraitExpression(
TraitExpression.NullSuperclass,
[] as const,
[] as const,
)
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
)