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