0.1.4 (#4)
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/4
This commit was merged in pull request #4.
This commit is contained in:
Julien Valverdé
2024-02-20 01:39:38 +01:00
parent c1c3c07524
commit de3b23018a
11 changed files with 535 additions and 362 deletions

View File

@@ -1,157 +1,136 @@
import { Fn, Pipe, Tuples } from "hotscript"
import { AbstractClass, Class, Opaque } from "type-fest"
import { TraitExpression, emptyTraitExpression } from "./TraitExpression"
import { AbstractTag } from "./abstract"
import { ExtendFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util"
export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper"
export type AddAbstractToImplClass<
ImplClass extends Class<{}, []>,
Abstract extends {},
> = (
Class<
Abstract & InstanceType<ImplClass>,
ConstructorParameters<ImplClass>
> &
StaticMembers<ImplClass>
)
export type RemoveAbstractFromImplClass<
ImplClassWithAbstract extends Class<Abstract, []> & { _tag: TraitApplierSuperTag },
Abstract extends {},
> = (
Class<
Omit<InstanceType<ImplClassWithAbstract>, keyof Abstract>,
ConstructorParameters<ImplClassWithAbstract>
> &
Omit<StaticMembers<ImplClassWithAbstract>, "_tag">
)
import { AbstractClass, Class, Simplify } from "type-fest"
import { TraitExpression } from "./TraitExpression"
import { Extend, StaticMembers } from "./util"
export class Trait<
Supertraits extends TraitExpression<typeof TraitExpression.NullSuperclass, Trait<any, any, any>[], Trait<any, any, any>[]>,
Abstract extends {},
ImplClass extends Class<{}, []>,
SuperExpression extends TraitExpression<
typeof TraitExpression.NullSuperclass,
Trait<any, any, any, any>[]
>,
Abstract extends object,
StaticAbstract extends object,
ImplClass extends AbstractClass<object, []>,
> {
constructor(
readonly supertraits: Supertraits,
readonly abstract: Abstract,
readonly apply: (Super: AbstractClass<{}>) => ImplClass,
readonly superExpression: SuperExpression,
readonly abstract: Abstract,
readonly staticAbstract: StaticAbstract,
readonly apply: (Super: AbstractClass<object>) => ImplClass,
) {}
}
export namespace Trait {
export type OwnSupertraits<T> = (
T extends Trait<infer Supertraits, any, any>
? Supertraits
export type SuperExpression<T> = (
T extends Trait<infer SuperExpression, any, any, any>
? SuperExpression
: never
)
export interface OwnSupertraitsFn extends Fn {
return: Trait.OwnSupertraits<this["arg0"]>
}
export type OwnAbstract<T> = (
T extends Trait<any, infer Abstract, any>
export type Supertraits<T> = (
TraitExpression.Traits<Trait.SuperExpression<T>>
)
export type Abstract<T> = (
T extends Trait<any, infer Abstract, any, any>
? Abstract
: never
)
export interface OwnAbstractFn extends Fn {
return: Trait.OwnAbstract<this["arg0"]>
}
export type OwnImplClass<T> = (
T extends Trait<any, any, infer ImplClass>
export type StaticAbstract<T> = (
T extends Trait<any, any, infer StaticAbstract, any>
? StaticAbstract
: never
)
export type ImplClass<T> = (
T extends Trait<any, any, any, infer ImplClass>
? ImplClass
: never
)
export interface OwnImplClassFn extends Fn {
return: Trait.OwnImplClass<this["arg0"]>
}
export type OwnImplInstance<T> = (
T extends Trait<any, any, infer ImplClass>
? InstanceType<ImplClass>
: never
export type ImplInstance<T> = (
InstanceType<Trait.ImplClass<T>>
)
export interface OwnImplInstanceFn extends Fn {
return: Trait.OwnImplInstance<this["arg0"]>
}
export type OwnClass<T> = (
T extends Trait<any, infer Abstract, infer ImplClass>
? AddAbstractToImplClass<ImplClass, Abstract>
: never
export type ImplStaticMembers<T> = (
StaticMembers<Trait.ImplClass<T>>
)
export interface OwnClassFn extends Fn {
return: Trait.OwnClass<this["arg0"]>
}
export type OwnInstance<T> = (
T extends Trait<any, infer Abstract, infer ImplClass>
? InstanceType<
AddAbstractToImplClass<ImplClass, Abstract>
>
: never
)
export interface OwnInstanceFn extends Fn {
return: Trait.OwnInstance<this["arg0"]>
}
export type Supertraits<T> = (
T extends Trait<infer Supertraits, any, any>
? TraitExpression.AllTraits<Supertraits>
: never
)
export interface SupertraitsFn extends Fn {
return: Trait.Supertraits<this["arg0"]>
}
export type Class<T> = (
AbstractClass<
Trait.Instance<T>,
any[]
> &
Pipe<T, [
Trait.SupertraitsFn,
Tuples.Append<T>,
Tuples.Map<Trait.OwnClassFn>,
Tuples.Map<StaticMembersFn>,
ExtendFn,
SimplifyFn,
]>
)
export interface ClassFn extends Fn {
return: Trait.Class<this["arg0"]>
}
export type Instance<T> = (
Pipe<T, [
Trait.SupertraitsFn,
Tuples.Append<T>,
Tuples.Map<Trait.OwnInstanceFn>,
ExtendFn,
SimplifyFn,
Extend<[
Trait.Abstract<T>,
Trait.ImplInstance<T>,
]>
)
export interface InstanceFn extends Fn {
return: Trait.Instance<this["arg0"]>
export type Static<T> = (
Extend<[
Trait.StaticAbstract<T>,
Trait.ImplStaticMembers<T>,
]>
)
}
export namespace TraitTuple {
export type MapAbstract<T> = {
[K in keyof T]: K extends keyof []
? T[K]
: Trait.Abstract<T[K]>
}
export type MapStaticAbstract<T> = {
[K in keyof T]: K extends keyof []
? T[K]
: Trait.StaticAbstract<T[K]>
}
export type MapImplClass<T> = {
[K in keyof T]: K extends keyof []
? T[K]
: Trait.ImplClass<T[K]>
}
export type MapImplInstance<T> = {
[K in keyof T]: K extends keyof []
? T[K]
: Trait.ImplInstance<T[K]>
}
export type MapImplStaticMembers<T> = {
[K in keyof T]: K extends keyof []
? T[K]
: Trait.ImplStaticMembers<T[K]>
}
export type MapInstance<T> = {
[K in keyof T]: K extends keyof []
? T[K]
: Trait.Instance<T[K]>
}
export type MapStaticMembers<T> = {
[K in keyof T]: K extends keyof []
? T[K]
: Trait.Static<T[K]>
}
}
export function trait<
Abstract extends {},
ImplClassWithAbstract extends Class<Abstract, []> & { _tag: TraitApplierSuperTag },
>(
abstract: Opaque<Abstract, AbstractTag>,
apply: (Super: AbstractClass<Abstract> & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract,
) {
return new Trait(
emptyTraitExpression,
abstract as Abstract,
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<ImplClassWithAbstract, Abstract>,
)
}
export type TraitClass<T extends Trait<any, any, any, any>> = (
AbstractClass<TraitInstance<T>, any[]> &
TraitStaticMembers<T>
)
export type TraitConcreteClass<T extends Trait<any, any, any, any>> = (
Class<TraitInstance<T>, any[]> &
TraitStaticMembers<T>
)
export type TraitInstance<T extends Trait<any, any, any, any>> = (
Simplify<Trait.Instance<T>>
)
export type TraitStaticMembers<T extends Trait<any, any, any, any>> = (
Simplify<Trait.Static<T>>
)