Files
thilatrait/src/trait.ts
Julien Valverdé d8e509f540
All checks were successful
continuous-integration/drone/push Build is passing
Refactoring
2023-12-13 19:55:14 +01:00

98 lines
2.2 KiB
TypeScript

import { AbstractClass, Class, UnionToIntersection } from "type-fest"
import { StaticMembers, copyProperties, flattenClass, getInheritanceHierarchy } from "./util/class"
export type Trait<T> =
AbstractClass<T, []>
// export function applyTrait<
// C extends Class<any, any> | AbstractClass<any, any>,
// TraitC extends Trait<any>,
// >(
// class_: C,
// trait: TraitC,
// ) {
// copyClassProperties(trait, class_)
// return class_ as (
// (C extends Class<any, any>
// ? Class<
// InstanceType<C> & InstanceType<TraitC>,
// ConstructorParameters<C>
// >
// : AbstractClass<
// InstanceType<C> & InstanceType<TraitC>,
// ConstructorParameters<C>
// >
// ) &
// StaticMembers<C> &
// StaticMembers<TraitC>
// )
// }
export const extendAndApplyTraits = <
C extends Class<any, any> | AbstractClass<any, any>,
Traits extends readonly Trait<any>[],
>(
classToExtend: C,
traits: Traits,
) =>
traits.reduce((class_, trait) => {
copyProperties(flattenClass(trait), class_)
return class_
}, class extends classToExtend {}) as (
AbstractClass<
InstanceType<C> &
UnionToIntersection<
InstanceType<Traits[number]>
>,
ConstructorParameters<C>
> &
StaticMembers<
C &
UnionToIntersection<
Traits[number]
>
>
)
export function expresses<
Traits extends readonly Trait<any>[]
>(
...traits: Traits
) {
const class_ = class {}
traits.forEach(trait => {
getInheritanceHierarchy(trait).forEach(current => {
copyProperties(
current,
class_,
["name", "length"],
["constructor"],
)
})
})
return class_ as unknown as (
Trait<
UnionToIntersection<
InstanceType<
Traits[number]
>
>
> &
StaticMembers<
UnionToIntersection<
Traits[number]
>
>
)
}