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> >, ConstructorParameters > & Simplify< Extend<[ StaticMembers, ...TraitTuple.MapImplStaticMembers, ]> > ) { return this.traits.reduce( (previous, trait) => trait.apply(previous), this.superclass, ) as any } staticImplements(_target: StaticImplements, _context: any) {} get staticImplementsStage2() { return (_target: StaticImplements) => {} } subtrait< This extends TraitExpression >( this: This ) { return new TraitBuilder> >, 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>, ]> > )