diff --git a/src/Trait.ts b/src/Trait.ts index 84516b2..8c0c210 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -9,43 +9,52 @@ export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" export type AddAbstractToImplClass< - ImplClass extends Class<{}, []>, - Abstract extends {}, + ImplClass extends Class<{}, []>, + Abstract extends {}, + StaticAbstract extends {}, > = ( Class< Abstract & InstanceType, ConstructorParameters > & + StaticAbstract & StaticMembers ) export type RemoveAbstractFromImplClass< ImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, Abstract extends {}, + StaticAbstract extends {}, > = ( Class< Omit, keyof Abstract>, ConstructorParameters > & - Omit, "_tag"> + Omit, keyof StaticAbstract | "_tag"> ) export class Trait< - Supertraits extends TraitExpression[], Trait[]>, - Abstract extends {}, - ImplClass extends Class<{}, []>, + Supertraits extends TraitExpression< + typeof TraitExpression.NullSuperclass, + Trait[], + Trait[] + >, + Abstract extends {}, + StaticAbstract extends {}, + ImplClass extends Class<{}, []>, > { constructor( - readonly supertraits: Supertraits, - readonly abstract: Abstract, - readonly apply: (Super: AbstractClass<{}>) => ImplClass, + readonly supertraits: Supertraits, + readonly abstract: Abstract, + readonly staticAbstract: StaticAbstract, + readonly apply: (Super: AbstractClass<{}>) => ImplClass, ) {} } export namespace Trait { export type OwnSupertraits = ( - T extends Trait + T extends Trait ? Supertraits : never ) @@ -54,7 +63,7 @@ export namespace Trait { } export type OwnAbstract = ( - T extends Trait + T extends Trait ? Abstract : never ) @@ -62,8 +71,17 @@ export namespace Trait { return: Trait.OwnAbstract } + export type OwnStaticAbstract = ( + T extends Trait + ? StaticAbstract + : never + ) + export interface OwnStaticAbstractFn extends Fn { + return: Trait.OwnAbstract + } + export type OwnImplClass = ( - T extends Trait + T extends Trait ? ImplClass : never ) @@ -72,38 +90,28 @@ export namespace Trait { } export type OwnImplInstance = ( - T extends Trait - ? InstanceType - : never + InstanceType> ) export interface OwnImplInstanceFn extends Fn { return: Trait.OwnImplInstance } export type OwnClass = ( - T extends Trait - ? AddAbstractToImplClass - : never + AddAbstractToImplClass, Trait.OwnAbstract, Trait.OwnStaticAbstract> ) export interface OwnClassFn extends Fn { return: Trait.OwnClass } export type OwnInstance = ( - T extends Trait - ? InstanceType< - AddAbstractToImplClass - > - : never + InstanceType> ) export interface OwnInstanceFn extends Fn { return: Trait.OwnInstance } export type Supertraits = ( - T extends Trait - ? TraitExpression.AllTraits - : never + TraitExpression.AllTraits> ) export interface SupertraitsFn extends Fn { return: Trait.Supertraits @@ -144,14 +152,17 @@ export namespace Trait { export function trait< Abstract extends {}, + StaticAbstract extends {}, ImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, >( - abstract: Opaque, - apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract, + abstract: Opaque, + staticAbstract: Opaque, + apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract, ) { return new Trait( emptyTraitExpression, - abstract as Abstract, - apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + abstract as Abstract, + staticAbstract as StaticAbstract, + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, ) } diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index d5bfed3..20ddbc5 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -14,8 +14,8 @@ import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpression< Superclass extends AbstractClass<{}>, - const OwnTraits extends Trait[], - const AllTraits extends Trait[], + const OwnTraits extends Trait[], + const AllTraits extends Trait[], > { constructor( readonly superclass: Superclass, @@ -52,17 +52,20 @@ export class TraitExpression< subtrait< This extends TraitExpression, SubtraitAbstract extends Implements, + SubtraitStaticAbstract extends StaticImplements, SubtraitImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, >( - this: This, - abstract: (expression: This) => Opaque, - apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => SubtraitImplClassWithAbstract, + this: This, + abstract: (expression: This) => Opaque, + staticAbstract: (expression: This) => Opaque, + apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => SubtraitImplClassWithAbstract, ) { return new Trait( this, // {} as RemoveSupertraitsAbstractFromAbstract>, - {} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements from this. - apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + {} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements from this. + {} as SubtraitStaticAbstract, + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, ) } } @@ -111,3 +114,12 @@ export type Implements> = ( SimplifyFn, ]> ) + +export type StaticImplements> = ( + Pipe, + ExtendFn, + SimplifyFn, + ]> +) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index c1f5064..8ab8d30 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -5,7 +5,7 @@ import { TraitExpression, emptyTraitExpression } from "./TraitExpression" import { ExtendableFn, StaticMembersFn } from "./util" -type SpreadSupertraits[]> = ( +type SpreadSupertraits[]> = ( Call< Tuples.FlatMap, Traits @@ -18,7 +18,7 @@ interface PrependTraitSupertraitsFn extends Fn { type AbstractMembersExtendable< Superclass extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > = ( Pipe, @@ -28,7 +28,7 @@ type AbstractMembersExtendable< type ImplInstanceExtendable< Superclass extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > = ( Pipe, @@ -38,7 +38,7 @@ type ImplInstanceExtendable< type ImplStaticMembersExtendable< Superclass extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > = ( Pipe, @@ -50,8 +50,8 @@ type ImplStaticMembersExtendable< type BuildTraitExpression< Superclass extends AbstractClass<{}>, - OwnTraits extends Trait[], - AllTraits extends Trait[], + OwnTraits extends Trait[], + AllTraits extends Trait[], > = ( AbstractMembersExtendable extends false ? "Type conflict between the traits abstract members and/or the superclass instance." @@ -65,8 +65,8 @@ type BuildTraitExpression< class TraitExpressionBuilder< Superclass extends AbstractClass<{}>, - const OwnTraits extends Trait[], - const AllTraits extends Trait[], + const OwnTraits extends Trait[], + const AllTraits extends Trait[], > { constructor(private expression: TraitExpression) {} @@ -85,7 +85,7 @@ class TraitExpressionBuilder< } expresses< - const Traits extends Trait[] + const Traits extends Trait[] >( ...traits: Traits ): TraitExpressionBuilder< @@ -104,7 +104,8 @@ class TraitExpressionBuilder< private spreadSupertraits< const Traits extends Trait< - TraitExpression[]>, + TraitExpression[]>, + any, any, any >[] diff --git a/src/tests.ts b/src/tests.ts index 5a3e955..c3194b2 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,10 +1,11 @@ import { Trait, trait } from "./Trait" -import { Implements } from "./TraitExpression" +import { Implements, StaticImplements } from "./TraitExpression" import { expression } from "./TraitExpressionBuilder" import { abstract } from "./abstract" const PrintsHelloOnNew = trait( + abstract(), abstract(), Super => class PrintsHelloOnNew extends Super { static readonly isPrintsHelloOnNew = true @@ -19,6 +20,7 @@ type PrintsHelloOnNewClass = Trait.Class const Identifiable = () => trait( abstract<{ readonly id: ID }>(), + abstract(), Super => class Identifiable extends Super { equals(el: Identifiable) { return this.id === el.id @@ -35,6 +37,7 @@ const StatefulSubscription = trait( { _tag: "expired", expiredSince: Date } ) }>(), + abstract(), Super => class StatefulSubscription extends Super {}, ) @@ -53,6 +56,8 @@ const ActiveStatefulSubscription = expression return abstract() }, + exp => abstract>(), + Super => class ActiveStatefulSubscription extends Super {}, ) @@ -86,7 +91,9 @@ class User extends exp.extends implements Implements { console.log(new User()) -declare function StaticImplements(target: { issou: string }, context: any): typeof target +declare function StaticImplements(target: { issou: string }, context: any): void @StaticImplements -class Gneugneu {} +class Gneugneu { + // static issou: string = "juif" +}