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:
231
src/Trait.ts
231
src/Trait.ts
@@ -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>>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user