import { AbstractClass, Class, Simplify } from "type-fest" import { Trait, TraitTuple } from "./Trait" import { TraitBuilder } from "./TraitBuilder" import { Extend, StaticMembers } from "./util" export class TraitExpression< Superclass extends AbstractClass, const Traits extends readonly Trait[], > { constructor( readonly superclass: Superclass, readonly traits: Traits, ) {} get extends(): ( AbstractClass< InstanceType & // Keep the instance of the superclass outside of any kind of type manipulation // as it can accidentely remove abstract properties Simplify< Extend< TraitTuple.MapImplInstance > >, ConstructorParameters > & Simplify< Extend<[ StaticMembers, ...TraitTuple.MapImplStaticMembers, ]> > ) { return this.traits.reduce( (previous, trait) => trait.apply(previous), this.superclass, ) as any } staticImplements(target: StaticImplements, context: any) {} subtrait< This extends TraitExpression >( this: This ) { return new TraitBuilder< This, Simplify< Extend> >, Simplify< Extend> >, AbstractClass< Simplify< Extend> > > & Simplify< Extend> > >( this, {} as any, {} as any, Super => class extends Super {} as any, ) } } export namespace TraitExpression { const nullSuperclassSymbol = Symbol() export class NullSuperclass { static readonly [nullSuperclassSymbol]: true constructor(...args: any[]) {} } export type Superclass = ( T extends TraitExpression ? Superclass : never ) export type Traits = ( T extends TraitExpression ? Traits : never ) } export type Implements< Exp extends TraitExpression[]> > = ( Simplify< Extend< TraitTuple.MapAbstract< TraitExpression.Traits > > > ) export type StaticImplements< Exp extends TraitExpression[]> > = ( Simplify< Extend< TraitTuple.MapStaticAbstract< TraitExpression.Traits > > > ) export type TraitExpressionClass< Exp extends TraitExpression[]> > = ( AbstractClass< TraitExpressionInstance, ConstructorParameters> > & TraitExpressionStaticMembers ) export type TraitExpressionConcreteClass< Exp extends TraitExpression[]> > = ( Class< TraitExpressionInstance, ConstructorParameters> > & TraitExpressionStaticMembers ) export type TraitExpressionInstance< Exp extends TraitExpression[]> > = ( InstanceType> & // Keep the instance of the superclass outside of any kind of type manipulation // as it can accidentely remove abstract properties Simplify< Extend< TraitTuple.MapInstance> > > ) export type TraitExpressionStaticMembers< Exp extends TraitExpression[]> > = ( Simplify< Extend<[ StaticMembers>, ...TraitTuple.MapStaticMembers>, ]> > )