From f5ab00c34aeb5f5656df7f9ecd95771aa77dfa95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 28 Jan 2024 19:56:12 +0100 Subject: [PATCH 01/65] Trait reimplementation work --- src/trait.ts | 157 ++++++++++++++++----------------------------------- 1 file changed, 48 insertions(+), 109 deletions(-) diff --git a/src/trait.ts b/src/trait.ts index 21fd00c..a6d647a 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,117 +1,56 @@ -import { AbstractClass, AbstractConstructor, Opaque } from "type-fest" +import { AbstractClass, Class, Opaque } from "type-fest" +import { StaticMembers } from "./util" -/** - * Represents a trait that can be applied to a class. - * @template C - The abstract class type. - */ -export type Trait< - C extends AbstractClass -> = Opaque< - TraitApplier, - "@thilawyn/thilatrait/Trait" -> - -export type TraitApplierSuperTag = "@thilawyn/thilatrait/Super" - -/** - * Represents the function signature for applying a trait to a parent class. - * @template C - The abstract class type. - */ -export type TraitApplier< - C extends AbstractClass +type RemoveAbstractMembersFromImpl< + ImplWithAbstractMembers extends Class, + AbstractMembers extends object, > = ( - (Super: Opaque, TraitApplierSuperTag>) => Opaque + Class< + Omit, keyof AbstractMembers>, + ConstructorParameters + > & + StaticMembers ) -/** - * Creates a trait using the provided trait applier function. - * @template C - The abstract class type. - * @param applier - The trait applier function. - * @returns A trait. - * @example - * Creates a trait: - * ```ts - * const Permissible = trait(Super => { - * abstract class Permissible extends Super { - * static readonly defaultPermissions: string[] = [] - * permissions: string[] = [] - * - * // Constructor is optional - * // If you wish to use it, make sure it takes any[] as an args array and passes it to the super call. This is necessary for inheritance to work properly. - * // Trait constructors cannot have typed arguments of their own, they only serve to run logic during object instantiation. - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return Permissible - * }) - * ``` - * Creates a generic trait: - * ```ts - * const Identifiable = () => - * trait(Super => { - * abstract class Identifiable extends Super { - * abstract readonly id: ID - * - * equals(el: Identifiable) { - * return this.id === el.id - * } - * - * // Optional - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return Identifiable - * }) - * ``` - * Creates a subtrait: - * ```ts - * const ImplementsIdentifiable = (defaultID: ID) => - * trait(Super => { - * abstract class ImplementsIdentifiable extends extendsAndExpresses( - * Super, - * Identifiable(), - * ) { - * id: ID = defaultID - * - * // Optional - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return ImplementsIdentifiable - * }) - * ``` - */ + +export type TraitTag = "@thilawyn/traitify-ts/Trait" + +export type Trait< + AbstractMembers extends object, + Impl extends Class, +> = ( + Opaque<{ + readonly AbstractMembers: AbstractMembers + readonly Impl: Impl + }, TraitTag> +) + + +export type TraitApplierSuperTag = "@thilawyn/traitify-ts/Super" + +export type TraitApplier< + AbstractMembers extends object, + ImplWithAbstractMembers extends Class, +> = ( + (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ) +) + + export function trait< - C extends AbstractClass ->( - applier: TraitApplier + AbstractMembers extends object = {} +>(): ( + >( + applier: TraitApplier + ) => Trait< + AbstractMembers, + RemoveAbstractMembersFromImpl< + ImplWithAbstractMembers, + AbstractMembers + > + > ) { - return applier as Trait + return (applier) => applier() } - -/** - * Returns the class type of a trait. - * @template T - The trait type. - */ -export type TraitClass = ( - T extends Trait - ? C - : never -) - -/** - * Returns the instance type of a trait. - * @template T - The trait type. - */ -export type TraitInstance = ( - T extends Trait - ? InstanceType - : never -) -- 2.49.1 From e46f78d93eed7cad734979f41f26e05912e4f64a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 28 Jan 2024 20:16:10 +0100 Subject: [PATCH 02/65] Trait work --- src/tests.ts | 131 +-------------------------------------------------- src/trait.ts | 26 ++++++++-- 2 files changed, 23 insertions(+), 134 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index cff84f8..9a8400d 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,131 +1,4 @@ -import { AbstractClass } from "type-fest" -import { expresses, extendsAndExpresses, trait } from "." -import { ClassesInstances, MergeInheritanceTree } from "./util" +import { trait } from "." -const Identifiable = () => - trait(Super => { - abstract class Identifiable extends Super { - abstract readonly id: ID - - equals(el: Identifiable) { - return this.id === el.id - } - - constructor(...args: any[]) { - super(...args) - console.log("Identified constructor") - } - } - - return Identifiable - }) - -const ImplementsIdentifiable = (defaultID: ID) => - trait(Super => { - abstract class ImplementsIdentifiable extends extendsAndExpresses( - Super, - Identifiable(), - ) { - id: ID = defaultID - - constructor(...args: any[]) { - super(...args) - console.log("ImplementsIdentifiable constructor") - } - } - - return ImplementsIdentifiable - }) - - -const Permissible = trait(Super => { - abstract class Permissible extends Super { - static readonly defaultPermissions: string[] = [] - permissions: string[] = [] - - constructor(...args: any[]) { - super(...args) - console.log("Permissible constructor") - } - } - - return Permissible -}) - - -const UserProto = expresses( - // Identifiable(), - ImplementsIdentifiable(0n), - Permissible, -) - -class User extends UserProto { - constructor(id: bigint) { - super() - this.id = id - } -} - -const user1 = new User(1n) -console.log(user1) -console.log(user1.equals(user1)) - - -const Test1 = trait(Super => { - abstract class Test1 extends Super { - declare static name: string - declare static testValue: ( - { _tag: "type1", value: string } | - { _tag: "type2", value: number } - ) - - abstract name: string - - declare createdAt: Date - declare readonly status: ( - { _tag: "awaitingPayment" } | - { _tag: "active", activeSince: Date, expiresAt?: Date } | - { _tag: "expired", expiredSince: Date } - ) - } - - return Test1 -}) - -const Test2 = trait(Super => { - abstract class Test2 extends Super { - declare readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } - } - - return Test2 -}) - -const Test3 = trait(Super => { - abstract class Test3 extends Super { - declare static testValue: { _tag: "type2", value: number } - declare lol: 10n - } - - return Test3 -}) - -const TestObjectProto = expresses(Test1, Test2, Test3) -TestObjectProto.testValue - - -interface Gneugneu { - ahi: string - get adolf(): string -} - -class GneugneuImpl implements Gneugneu { - ahi: string = "" - get adolf(): string { - throw new Error("Method not implemented.") - } - -} - -abstract class Issou extends GneugneuImpl implements Gneugneu { -} +const PrintsHelloOnNew = trait() diff --git a/src/trait.ts b/src/trait.ts index a6d647a..fe1898a 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -2,6 +2,17 @@ import { AbstractClass, Class, Opaque } from "type-fest" import { StaticMembers } from "./util" +type AddAbstractMembersToImpl< + Impl extends Class, + AbstractMembers extends object, +> = ( + Class< + InstanceType & AbstractMembers, + ConstructorParameters + > & + StaticMembers +) + type RemoveAbstractMembersFromImpl< ImplWithAbstractMembers extends Class, AbstractMembers extends object, @@ -18,11 +29,16 @@ export type TraitTag = "@thilawyn/traitify-ts/Trait" export type Trait< AbstractMembers extends object, - Impl extends Class, + Impl extends Class, > = ( Opaque<{ - readonly AbstractMembers: AbstractMembers - readonly Impl: Impl + readonly apply: TraitApplier< + AbstractMembers, + AddAbstractMembersToImpl< + Impl, + AbstractMembers + > + > }, TraitTag> ) @@ -43,7 +59,7 @@ export function trait< AbstractMembers extends object = {} >(): ( >( - applier: TraitApplier + apply: TraitApplier ) => Trait< AbstractMembers, RemoveAbstractMembersFromImpl< @@ -52,5 +68,5 @@ export function trait< > > ) { - return (applier) => applier() + return apply => ({ apply }) as any } -- 2.49.1 From 096d4a92e770777b87c86813e95865a5cb390c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 28 Jan 2024 20:23:44 +0100 Subject: [PATCH 03/65] Trait examples --- src/tests.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tests.ts b/src/tests.ts index 9a8400d..59df546 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,20 @@ import { trait } from "." -const PrintsHelloOnNew = trait() +const PrintsHelloOnNew = trait()(Super => + class PrintsHelloOnNew extends Super { + constructor(...args: any[]) { + super(...args) + console.log("Hello!") + } + } +) + +const Identifiable = () => + trait<{ id: ID }>()(Super => + class Identifiable extends Super { + equals(el: Identifiable) { + return this.id === el.id + } + } + ) -- 2.49.1 From 8b01a13d7cdf55ea05a2d2bfbb04753093bf5b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 28 Jan 2024 22:52:32 +0100 Subject: [PATCH 04/65] Expresses work --- src/expresses.ts | 106 ++++++++++++++++------------------------------ src/tests.ts | 12 ++++-- src/trait.ts | 27 +++++++++++- src/util/trait.ts | 22 ++++++---- 4 files changed, 84 insertions(+), 83 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 5784e56..d8dbe4c 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,84 +1,50 @@ import { AbstractClass, Opaque } from "type-fest" import { Trait, TraitApplierSuperTag } from "." -import { ClassesInstances, ClassesStaticMembers, MergeInheritanceTree, MergeInheritanceTreeWithoutOverriding, StaticMembers, TraitsClasses } from "./util" +import { MergeInheritanceTree, TraitsAbstractMembers } from "./util" + + +class TraitsExpression< + Super extends AbstractClass, + Traits extends readonly Trait[], +> { + constructor( + readonly superclass: Super, + readonly traits: Traits, + ) {} + + implements(): ( + MergeInheritanceTree< + TraitsAbstractMembers + > + ) { + return {} as any + } + + extends() { + return this.traits.reduce( + (previous, trait) => trait.apply(previous), + this.superclass as Opaque, + ) + } +} -/** - * Extends a class with the given traits and expresses their combined functionality. - * @template C - The abstract class type. - * @template Traits - An array of traits. - * @param extend - The class to extend. - * @param traits - An array of traits to apply. - * @returns A new class type expressing the combined functionality of the base class and traits. - * @example - * Extends a superclass and applies traits: - * ```ts - * class User extends extendsAndExpresses(Entity, - * Identifiable(), - * Permissible, - * ) { - * readonly id: bigint - * - * constructor(id: bigint) { - * super() - * this.id = id - * } - * } - * ``` - */ export function extendsAndExpresses< - C extends AbstractClass, - Traits extends readonly Trait[], + Super extends AbstractClass, + Traits extends readonly Trait[], >( - extend: C, - ...traits: Traits + superclass: Super, + ...traits: Traits ) { - return traits.reduce( - (previous, trait) => trait(previous), - extend as Opaque, - ) as unknown as ( - AbstractClass< - MergeInheritanceTreeWithoutOverriding<[ - InstanceType, - ...ClassesInstances< - TraitsClasses - >, - ]>, - - ConstructorParameters - > & - - MergeInheritanceTree<[ - StaticMembers, - ...ClassesStaticMembers< - TraitsClasses - >, - ]> - ) + return new TraitsExpression(superclass, traits) } -/** - * Expresses the combined functionality of multiple traits. - * @template Traits - An array of trait. - * @param traits - An array of trait to apply. - * @returns A new class type expressing the combined functionality of the traits. - * @example - * Applies traits to a class: - * ```ts - * class User extends expresses(Identifiable(), Permissible) { - * readonly id: bigint - * - * constructor(id: bigint) { - * super() - * this.id = id - * } - * } - * ``` - */ +class DefaultSuperclass {} + export function expresses< - Traits extends readonly Trait[], + Traits extends readonly Trait[], >( ...traits: Traits ) { - return extendsAndExpresses(Object, ...traits) + return new TraitsExpression(DefaultSuperclass, traits) } diff --git a/src/tests.ts b/src/tests.ts index 59df546..9b096a8 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { trait } from "." +import { expresses, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -10,11 +10,17 @@ const PrintsHelloOnNew = trait()(Super => } ) -const Identifiable = () => - trait<{ id: ID }>()(Super => +const Identifiable = () => ( + trait<{ readonly id: ID }>()(Super => class Identifiable extends Super { equals(el: Identifiable) { return this.id === el.id } } ) +) + + +const exp = expresses(Identifiable()) + +class User implements typeof exp.implements() diff --git a/src/trait.ts b/src/trait.ts index fe1898a..6736755 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -42,8 +42,32 @@ export type Trait< }, TraitTag> ) +export type TraitAbstractMembers = ( + T extends Trait + ? AbstractMembers + : never +) -export type TraitApplierSuperTag = "@thilawyn/traitify-ts/Super" +export type TraitImpl = ( + T extends Trait + ? Impl + : never +) + +export type TraitClass = ( + T extends Trait + ? AddAbstractMembersToImpl + : never +) + +export type TraitInstance = ( + T extends Trait + ? InstanceType & AbstractMembers + : never +) + + +export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" export type TraitApplier< AbstractMembers extends object, @@ -54,7 +78,6 @@ export type TraitApplier< ) ) - export function trait< AbstractMembers extends object = {} >(): ( diff --git a/src/util/trait.ts b/src/util/trait.ts index 149599d..83153cd 100644 --- a/src/util/trait.ts +++ b/src/util/trait.ts @@ -1,14 +1,20 @@ -import { Trait, TraitClass } from ".." +import { Trait, TraitAbstractMembers, TraitClass } from ".." -/** - * Represents an array of classes corresponding to the provided traits. - * @template Traits - An array of traits extending Trait. - */ -export type TraitsClasses[]> = ( +export type TraitsAbstractMembers[]> = ( Traits extends [infer T, ...infer Rest] - ? T extends Trait - ? Rest extends Trait[] + ? T extends Trait + ? Rest extends Trait[] + ? [TraitAbstractMembers, ...TraitsClasses] + : never + : never + : [] +) + +export type TraitsClasses[]> = ( + Traits extends [infer T, ...infer Rest] + ? T extends Trait + ? Rest extends Trait[] ? [TraitClass, ...TraitsClasses] : never : never -- 2.49.1 From 9834856e8bea1d09f03688b74ab8241a78d5248c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 28 Jan 2024 23:43:39 +0100 Subject: [PATCH 05/65] Tests --- src/tests.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index 9b096a8..0cc019f 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,5 @@ -import { expresses, trait } from "." +import { Simplify } from "type-fest" +import { TraitAbstractMembers, TraitImpl, TraitInstance, expresses, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -21,6 +22,10 @@ const Identifiable = () => ( ) +type Test = Simplify>>> + const exp = expresses(Identifiable()) -class User implements typeof exp.implements() +class User implements ReturnType { + id: bigint = -1n +} -- 2.49.1 From ecbf936f8507cbc5d9d3a1804f4fd032689c7c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 29 Jan 2024 01:42:14 +0100 Subject: [PATCH 06/65] Tests --- src/tests.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index 0cc019f..8533832 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,5 @@ import { Simplify } from "type-fest" -import { TraitAbstractMembers, TraitImpl, TraitInstance, expresses, trait } from "." +import { TraitAbstractMembers, TraitClass, TraitImpl, TraitInstance, expresses, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -22,7 +22,9 @@ const Identifiable = () => ( ) -type Test = Simplify>>> +type Test = Simplify>>> + +const appliedIdentifiable = Identifiable().apply({} as any) const exp = expresses(Identifiable()) -- 2.49.1 From 754a5dc4202a81e2cc49d6febafec66d1d2d91e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 29 Jan 2024 02:54:47 +0100 Subject: [PATCH 07/65] TraitImplInstance --- src/tests.ts | 4 ++-- src/trait.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index 8533832..e1f29af 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,5 @@ import { Simplify } from "type-fest" -import { TraitAbstractMembers, TraitClass, TraitImpl, TraitInstance, expresses, trait } from "." +import { TraitAbstractMembers, TraitClass, TraitImpl, TraitImplInstance, TraitInstance, expresses, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -22,7 +22,7 @@ const Identifiable = () => ( ) -type Test = Simplify>>> +type Test = Simplify>>> const appliedIdentifiable = Identifiable().apply({} as any) diff --git a/src/trait.ts b/src/trait.ts index 6736755..46fddb8 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -54,6 +54,12 @@ export type TraitImpl = ( : never ) +export type TraitImplInstance = ( + T extends Trait + ? InstanceType + : never +) + export type TraitClass = ( T extends Trait ? AddAbstractMembersToImpl -- 2.49.1 From 3aade48a7d2ca59cce86968d5f2a065a8af3493a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 29 Jan 2024 03:23:09 +0100 Subject: [PATCH 08/65] Trait refactoring --- src/tests.ts | 2 +- src/trait.ts | 51 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index e1f29af..b0abcf5 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,5 @@ import { Simplify } from "type-fest" -import { TraitAbstractMembers, TraitClass, TraitImpl, TraitImplInstance, TraitInstance, expresses, trait } from "." +import { TraitImplInstance, expresses, trait } from "." const PrintsHelloOnNew = trait()(Super => diff --git a/src/trait.ts b/src/trait.ts index 46fddb8..c300475 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -13,12 +13,23 @@ type AddAbstractMembersToImpl< StaticMembers ) +type RemoveAbstractMembersFromImplInstance< + ImplInstanceWithAbstractMembers extends AbstractMembers, + AbstractMembers extends object, +> = ( + Omit +) + type RemoveAbstractMembersFromImpl< ImplWithAbstractMembers extends Class, AbstractMembers extends object, > = ( Class< - Omit, keyof AbstractMembers>, + RemoveAbstractMembersFromImplInstance< + InstanceType, + AbstractMembers + >, + ConstructorParameters > & StaticMembers @@ -28,16 +39,13 @@ type RemoveAbstractMembersFromImpl< export type TraitTag = "@thilawyn/traitify-ts/Trait" export type Trait< - AbstractMembers extends object, - Impl extends Class, + AbstractMembers extends object, + ImplWithAbstractMembers extends Class, > = ( Opaque<{ readonly apply: TraitApplier< AbstractMembers, - AddAbstractMembersToImpl< - Impl, - AbstractMembers - > + ImplWithAbstractMembers > }, TraitTag> ) @@ -48,27 +56,33 @@ export type TraitAbstractMembers = ( : never ) -export type TraitImpl = ( - T extends Trait - ? Impl +export type TraitImplClass = ( + T extends Trait + ? RemoveAbstractMembersFromImpl< + ImplWithAbstractMembers, + AbstractMembers + > : never ) export type TraitImplInstance = ( - T extends Trait - ? InstanceType + T extends Trait + ? RemoveAbstractMembersFromImplInstance< + InstanceType, + AbstractMembers + > : never ) export type TraitClass = ( - T extends Trait - ? AddAbstractMembersToImpl + T extends Trait + ? ImplWithAbstractMembers : never ) export type TraitInstance = ( - T extends Trait - ? InstanceType & AbstractMembers + T extends Trait + ? InstanceType : never ) @@ -91,10 +105,7 @@ export function trait< apply: TraitApplier ) => Trait< AbstractMembers, - RemoveAbstractMembersFromImpl< - ImplWithAbstractMembers, - AbstractMembers - > + ImplWithAbstractMembers > ) { return apply => ({ apply }) as any -- 2.49.1 From f59706d9946dcf6818ce86b393c404312fc9bd0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 29 Jan 2024 03:33:43 +0100 Subject: [PATCH 09/65] Tests --- src/tests.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index b0abcf5..51fd74c 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,6 @@ import { Simplify } from "type-fest" -import { TraitImplInstance, expresses, trait } from "." +import { TraitAbstractMembers, TraitImplInstance, expresses, trait } from "." +import { MergeInheritanceTree, TraitsAbstractMembers } from "./util" const PrintsHelloOnNew = trait()(Super => @@ -22,11 +23,16 @@ const Identifiable = () => ( ) -type Test = Simplify>>> +// type Test = Simplify>>> +type Test1 = [ + TraitAbstractMembers>>, + TraitAbstractMembers>> +] +type Test2 = MergeInheritanceTree const appliedIdentifiable = Identifiable().apply({} as any) -const exp = expresses(Identifiable()) +const exp = expresses(Identifiable(), Identifiable()) class User implements ReturnType { id: bigint = -1n -- 2.49.1 From bb6172381f4620a3554b029a84e9c9ae2ec2966e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 29 Jan 2024 16:59:37 +0100 Subject: [PATCH 10/65] Tests --- src/tests.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index 51fd74c..b7b0f5e 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -22,13 +22,31 @@ const Identifiable = () => ( ) ) +const StatefulSubscription = trait<{ + readonly status: ( + { _tag: "awaitingPayment" } | + { _tag: "active", activeSince: Date, expiresAt?: Date } | + { _tag: "expired", expiredSince: Date } + ) +}>()(Super => + class StatefulSubscription extends Super {} +) + +interface ActiveStatefulSubscriptionAbstractMembers extends TraitAbstractMembers { + readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } +} + +const ActiveStatefulSubscription = trait()(Super => + class ActiveStatefulSubscription extends Super {} +) + // type Test = Simplify>>> type Test1 = [ - TraitAbstractMembers>>, - TraitAbstractMembers>> + TraitAbstractMembers, + TraitAbstractMembers, ] -type Test2 = MergeInheritanceTree +type Test2 = Simplify> const appliedIdentifiable = Identifiable().apply({} as any) -- 2.49.1 From 5f0d21d93b8b2760a86698895bf6ef317863d72d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 29 Jan 2024 17:27:15 +0100 Subject: [PATCH 11/65] HOTScript tests --- bun.lockb | Bin 155330 -> 155966 bytes package.json | 1 + src/tests.ts | 24 ++++++++++++++++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/bun.lockb b/bun.lockb index 1263665f93f6bc4a12cda1f583a67208e60cbb22..3bf296d63c0a969426dbea7d9fd89377daa85799 100755 GIT binary patch delta 27301 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

gHzxnI0Mdt^WYp9$RHa4`T;rV1cOlUEqV2! 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 delta 26899 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 LF7<2m%_IK{osRdK diff --git a/package.json b/package.json index acb7aa9..499169b 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "clean:node": "rm -rf node_modules" }, "dependencies": { + "hotscript": "^1.0.13", "type-fest": "^4.10.1" }, "devDependencies": { diff --git a/src/tests.ts b/src/tests.ts index b7b0f5e..aedbc6e 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,6 +1,7 @@ import { Simplify } from "type-fest" -import { TraitAbstractMembers, TraitImplInstance, expresses, trait } from "." +import { Trait, TraitAbstractMembers, TraitImplInstance, expresses, trait } from "." import { MergeInheritanceTree, TraitsAbstractMembers } from "./util" +import { Call, Fn, Tuples } from "hotscript" const PrintsHelloOnNew = trait()(Super => @@ -41,12 +42,31 @@ const ActiveStatefulSubscription = trait + ? AbstractMembers + : never +} + // type Test = Simplify>>> type Test1 = [ TraitAbstractMembers, TraitAbstractMembers, ] -type Test2 = Simplify> +type Test2 = TraitsAbstractMembers<[ + typeof StatefulSubscription, + typeof ActiveStatefulSubscription, +]> +type Test3 = Simplify< + MergeInheritanceTree< + Call, [ + typeof StatefulSubscription, + typeof ActiveStatefulSubscription, + ]> + > +> +// type Test2 = Simplify> + const appliedIdentifiable = Identifiable().apply({} as any) -- 2.49.1 From e493331ff3b381a99c4589f3be8bc64aa336a404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 29 Jan 2024 18:39:20 +0100 Subject: [PATCH 12/65] Work --- src/tests.ts | 19 +++++-------------- src/trait.ts | 21 +++++++++++++++++++++ src/util/extend.ts | 0 3 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 src/util/extend.ts diff --git a/src/tests.ts b/src/tests.ts index aedbc6e..39aece7 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,5 @@ import { Simplify } from "type-fest" -import { Trait, TraitAbstractMembers, TraitImplInstance, expresses, trait } from "." +import { GetTraitAbstractMembers, GetTraitClass, GetTraitImplClass, GetTraitImplInstance, GetTraitInstance, Trait, TraitAbstractMembers, TraitImplInstance, expresses, trait } from "." import { MergeInheritanceTree, TraitsAbstractMembers } from "./util" import { Call, Fn, Tuples } from "hotscript" @@ -41,13 +41,6 @@ const ActiveStatefulSubscription = trait - ? AbstractMembers - : never -} - // type Test = Simplify>>> type Test1 = [ TraitAbstractMembers, @@ -58,12 +51,10 @@ type Test2 = TraitsAbstractMembers<[ typeof ActiveStatefulSubscription, ]> type Test3 = Simplify< - MergeInheritanceTree< - Call, [ - typeof StatefulSubscription, - typeof ActiveStatefulSubscription, - ]> - > + Call, [ + typeof StatefulSubscription, + typeof ActiveStatefulSubscription, + ]> > // type Test2 = Simplify> diff --git a/src/trait.ts b/src/trait.ts index c300475..a73f4d1 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,3 +1,4 @@ +import { Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" import { StaticMembers } from "./util" @@ -56,6 +57,10 @@ export type TraitAbstractMembers = ( : never ) +export interface GetTraitAbstractMembers extends Fn { + return: TraitAbstractMembers +} + export type TraitImplClass = ( T extends Trait ? RemoveAbstractMembersFromImpl< @@ -65,6 +70,10 @@ export type TraitImplClass = ( : never ) +export interface GetTraitImplClass extends Fn { + return: TraitImplClass +} + export type TraitImplInstance = ( T extends Trait ? RemoveAbstractMembersFromImplInstance< @@ -74,18 +83,30 @@ export type TraitImplInstance = ( : never ) +export interface GetTraitImplInstance extends Fn { + return: TraitImplInstance +} + export type TraitClass = ( T extends Trait ? ImplWithAbstractMembers : never ) +export interface GetTraitClass extends Fn { + return: TraitClass +} + export type TraitInstance = ( T extends Trait ? InstanceType : never ) +export interface GetTraitInstance extends Fn { + return: TraitInstance +} + export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" diff --git a/src/util/extend.ts b/src/util/extend.ts new file mode 100644 index 0000000..e69de29 -- 2.49.1 From ff3991ae454eddaf9df3d8a37a4dec5a4fcc8ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 31 Jan 2024 03:22:23 +0100 Subject: [PATCH 13/65] Working trait expression implements --- bun.lockb | Bin 155966 -> 155678 bytes src/expresses.ts | 30 +++++++++++++++++++----------- src/tests.ts | 31 ++++++++----------------------- src/trait.ts | 10 +++++----- src/util/extend.ts | 16 ++++++++++++++++ src/util/index.ts | 2 +- src/util/trait.ts | 22 ---------------------- 7 files changed, 49 insertions(+), 62 deletions(-) delete mode 100644 src/util/trait.ts diff --git a/bun.lockb b/bun.lockb index 3bf296d63c0a969426dbea7d9fd89377daa85799..c3c0b09247cff1be9abe12a541d885a7f62b184f 100755 GIT binary patch delta 1249 zcmXZbOGs2v9LMo!(y%&2UUHQ7TV!nB~N zM8h7MwP{n=MTiIy?cLQ%jf$dGi-@4U|C!&P`E!2fbI;s+&K;eY3J*<&`)bm9>$_`T z*ZR(W-;j9U@9W}sU8;_H=lHlZx>43Bo5#FK)+C$HyxJC1&9ZdzKD!CkB3nS-FKd-$ zU^OX=yJNx-ct8u=WMS-}?6@p~70FJ>GO=RWNm&%Dl(owiVrjBdNsBv|1^%I}I#ZgtFyAjy$0Q-o%CH8STbP>0#LgEsSBe zWnHpmSQXh$c~Q2UoS}7>7;V!l=x?+g=(5(WB!8!^;@!eLCO?wo+!fg><{xEOWviJ_ z%dW}RFn>$76J3|BB~QqD80~QRbd+p$Gi7mCz~mQgyXpn)`a1e2ZJV-_o2{p3XsbTi z2J#28ZJ=Mak^F^h8@R)04=$vq$yWCm?ageWvpm0lKH)xS*Nfsy=0c|xZJ6y?RJW0+y7w%vl$ht!WqtO3sl9`Vwjo~_gcAN%diW61O1A{ngFeqkItEj##zz8HwTB~LZIjfV*!Gd+LMo&pz7qAEN1TOaK4? delta 1534 zcmbW1*>6l?7{+EPm`ElSm1RZH!(5{YW#f(waBx^lr?uOuhp56~(ts>Ox2 zu~Z|NTGBLwAa*K|a77!DiYpf)5`OQ@^AGUmJaeA+_igWY=6t7PAlM%ZHkK##M2=M4 ztneC|y!Wk-n!HLs*(IXNbB@a;p)q3BVx!2nSp!icHX7d?C(hN1*<96Pbz(MGjaa={ z3VAIe_1%7c$B_ikN@VLahz0Rg$OVzy4XSaY2D z&ZPo(3Z78MG}tb&lVamx`C=_%>97K^RIuyv0RzoQ6Lp)+sg} zR*bh@c8Sfvr>I{ycPn}(`ig8rm((u@KY}bSCz$VYNxsFAb63=H7WoIUt75as2gQ2C z=8)gR+m5b@<>C9qdb!)?=Atm(;)d8f{14tgmxJj8T6;eFj&jj$vHAE<$l{Jz0saZz z3b-q_0RIJV1z1tG@Io|*w;14VPi7HH#amG^A7kx{QJUa=u_dr{u?J#HVVPnNx!cKD zh6a$uWA!V<_r^)0P+NF8`c1pVQ}y$UNdAym_0I%X;KPhC_FSwO{}FFHdLd@V)m}_1 z{-xL|d=}mceI>RUA4L|g#n#~aIAn47MzDk|i-oPyw_ZA$$DR_D(Ed z=Z}bVL=Uuh*OPtw!dQj&0oje}Q5~|CZ895d6Rk%Z&_=WgZAM$rR#b}0(0`06{P#i8 zyt7`m7izQvO}y`lZg2Mv215ZmRK(t)XspxA^#VMictl6KyvmYL_fVoef4H^mvlk2P P8BXM#k!Z${7e4$Km5zyO diff --git a/src/expresses.ts b/src/expresses.ts index d8dbe4c..fed933a 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,6 +1,7 @@ -import { AbstractClass, Opaque } from "type-fest" -import { Trait, TraitApplierSuperTag } from "." -import { MergeInheritanceTree, TraitsAbstractMembers } from "./util" +import { Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass, Opaque, Simplify } from "type-fest" +import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag } from "." +import { ExtendFn } from "./util" class TraitsExpression< @@ -12,14 +13,6 @@ class TraitsExpression< readonly traits: Traits, ) {} - implements(): ( - MergeInheritanceTree< - TraitsAbstractMembers - > - ) { - return {} as any - } - extends() { return this.traits.reduce( (previous, trait) => trait.apply(previous), @@ -29,6 +22,21 @@ class TraitsExpression< } +interface SimplifyFn extends Fn { + return: Simplify +} + +export type Implements> = ( + Exp extends TraitsExpression + ? Pipe, + ExtendFn, + SimplifyFn, + ]> + : never +) + + export function extendsAndExpresses< Super extends AbstractClass, Traits extends readonly Trait[], diff --git a/src/tests.ts b/src/tests.ts index 39aece7..104d0fe 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,7 +1,4 @@ -import { Simplify } from "type-fest" -import { GetTraitAbstractMembers, GetTraitClass, GetTraitImplClass, GetTraitImplInstance, GetTraitInstance, Trait, TraitAbstractMembers, TraitImplInstance, expresses, trait } from "." -import { MergeInheritanceTree, TraitsAbstractMembers } from "./util" -import { Call, Fn, Tuples } from "hotscript" +import { Implements, TraitAbstractMembers, expresses, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -41,28 +38,16 @@ const ActiveStatefulSubscription = trait>>> -type Test1 = [ - TraitAbstractMembers, - TraitAbstractMembers, -] -type Test2 = TraitsAbstractMembers<[ - typeof StatefulSubscription, - typeof ActiveStatefulSubscription, -]> -type Test3 = Simplify< - Call, [ - typeof StatefulSubscription, - typeof ActiveStatefulSubscription, - ]> -> + // type Test2 = Simplify> -const appliedIdentifiable = Identifiable().apply({} as any) +const exp = expresses( + Identifiable(), + // Identifiable() +) +type Impl = Implements -const exp = expresses(Identifiable(), Identifiable()) - -class User implements ReturnType { +class User implements Implements { id: bigint = -1n } diff --git a/src/trait.ts b/src/trait.ts index a73f4d1..a8b758e 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -57,7 +57,7 @@ export type TraitAbstractMembers = ( : never ) -export interface GetTraitAbstractMembers extends Fn { +export interface TraitAbstractMembersFn extends Fn { return: TraitAbstractMembers } @@ -70,7 +70,7 @@ export type TraitImplClass = ( : never ) -export interface GetTraitImplClass extends Fn { +export interface TraitImplClassFn extends Fn { return: TraitImplClass } @@ -83,7 +83,7 @@ export type TraitImplInstance = ( : never ) -export interface GetTraitImplInstance extends Fn { +export interface TraitImplInstanceFn extends Fn { return: TraitImplInstance } @@ -93,7 +93,7 @@ export type TraitClass = ( : never ) -export interface GetTraitClass extends Fn { +export interface TraitClassFn extends Fn { return: TraitClass } @@ -103,7 +103,7 @@ export type TraitInstance = ( : never ) -export interface GetTraitInstance extends Fn { +export interface TraitInstanceFn extends Fn { return: TraitInstance } diff --git a/src/util/extend.ts b/src/util/extend.ts index e69de29..c36ae4e 100644 --- a/src/util/extend.ts +++ b/src/util/extend.ts @@ -0,0 +1,16 @@ +import { Call, Fn, Tuples } from "hotscript" + + +type CommonKeys = Extract + +type ExtendReducer = ( + Pick> extends Pick> + ? Omit> & Self + : never +) +interface ExtendReducerFn extends Fn { + return: ExtendReducer +} + +export type ExtendFn = Tuples.Reduce +export type Extend = Call diff --git a/src/util/index.ts b/src/util/index.ts index c5faea6..bf58ac1 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1,3 +1,3 @@ export * from "./class" +export * from "./extend" export * from "./inheritance" -export * from "./trait" diff --git a/src/util/trait.ts b/src/util/trait.ts deleted file mode 100644 index 83153cd..0000000 --- a/src/util/trait.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Trait, TraitAbstractMembers, TraitClass } from ".." - - -export type TraitsAbstractMembers[]> = ( - Traits extends [infer T, ...infer Rest] - ? T extends Trait - ? Rest extends Trait[] - ? [TraitAbstractMembers, ...TraitsClasses] - : never - : never - : [] -) - -export type TraitsClasses[]> = ( - Traits extends [infer T, ...infer Rest] - ? T extends Trait - ? Rest extends Trait[] - ? [TraitClass, ...TraitsClasses] - : never - : never - : [] -) -- 2.49.1 From 11335f10cd9071d884b139dc673bd0bba5dbdef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 31 Jan 2024 05:21:56 +0100 Subject: [PATCH 14/65] Expresses work --- src/expresses.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index fed933a..189b81e 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,6 +1,6 @@ -import { Fn, Pipe, Tuples } from "hotscript" +import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Opaque, Simplify } from "type-fest" -import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag } from "." +import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplInstanceFn } from "." import { ExtendFn } from "./util" @@ -13,7 +13,16 @@ class TraitsExpression< readonly traits: Traits, ) {} - extends() { + extends(): ( + AbstractClass< + Call, + ...Call, Traits>, + ]>, + + ConstructorParameters + > + ) { return this.traits.reduce( (previous, trait) => trait.apply(previous), this.superclass as Opaque, -- 2.49.1 From a0aa9446d638b443079bc578f74f59a92a6137ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 31 Jan 2024 06:44:18 +0100 Subject: [PATCH 15/65] Working exp.extends() --- src/expresses.ts | 30 +++++++++++++++++++----------- src/tests.ts | 4 +++- src/util/class.ts | 5 +++++ src/util/index.ts | 1 + src/util/misc.ts | 7 +++++++ 5 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 src/util/misc.ts diff --git a/src/expresses.ts b/src/expresses.ts index 189b81e..716e76b 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,7 +1,7 @@ -import { Call, Fn, Pipe, Tuples } from "hotscript" -import { AbstractClass, Opaque, Simplify } from "type-fest" -import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplInstanceFn } from "." -import { ExtendFn } from "./util" +import { Call, Pipe, Tuples } from "hotscript" +import { AbstractClass, Opaque } from "type-fest" +import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "." +import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" class TraitsExpression< @@ -15,26 +15,34 @@ class TraitsExpression< extends(): ( AbstractClass< - Call, ...Call, Traits>, + ], [ + ExtendFn, + SimplifyFn, ]>, ConstructorParameters - > + > & + + Pipe<[ + Super, + ...Call, Traits>, + ], [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> ) { return this.traits.reduce( (previous, trait) => trait.apply(previous), this.superclass as Opaque, - ) + ) as any } } -interface SimplifyFn extends Fn { - return: Simplify -} - export type Implements> = ( Exp extends TraitsExpression ? Pipe -class User implements Implements { +class User extends exp.extends() implements Implements { id: bigint = -1n } + +new User().id diff --git a/src/util/class.ts b/src/util/class.ts index 325aba5..d8030d7 100644 --- a/src/util/class.ts +++ b/src/util/class.ts @@ -1,3 +1,4 @@ +import { Fn } from "hotscript" import { AbstractClass } from "type-fest" @@ -37,6 +38,10 @@ export type StaticMembers> = ( Omit ) +export interface StaticMembersFn extends Fn { + return: StaticMembers +} + /** * Represents an array of static members corresponding to the provided classes. * @template Classes - An array of classes extending AbstractClass. diff --git a/src/util/index.ts b/src/util/index.ts index bf58ac1..c0b49af 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1,3 +1,4 @@ export * from "./class" export * from "./extend" export * from "./inheritance" +export * from "./misc" diff --git a/src/util/misc.ts b/src/util/misc.ts new file mode 100644 index 0000000..d67c57e --- /dev/null +++ b/src/util/misc.ts @@ -0,0 +1,7 @@ +import { Fn } from "hotscript" +import { Simplify } from "type-fest" + + +export interface SimplifyFn extends Fn { + return: Simplify +} -- 2.49.1 From a5b8a1c184c3194b71cab778e3ab9ff78ca61351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 31 Jan 2024 06:50:27 +0100 Subject: [PATCH 16/65] Tests --- src/tests.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index b53d88d..965715b 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, TraitAbstractMembers, expresses, trait } from "." +import { Implements, TraitAbstractMembers, expresses, extendsAndExpresses, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -42,7 +42,13 @@ const ActiveStatefulSubscription = trait> -const exp = expresses( +class TestSuperclass { + id: number = 69 +} + + +const exp = extendsAndExpresses( + TestSuperclass, Identifiable(), // Identifiable() ) -- 2.49.1 From a82c978c9e394e951731e04cbce4a08d7f78a51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 1 Feb 2024 02:21:10 +0100 Subject: [PATCH 17/65] Extendable --- src/expresses.ts | 38 ++++++++++++++++++++++++++++++++------ src/tests.ts | 10 ++++++++-- src/util/extend.ts | 12 +++++++++++- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 716e76b..5b9ed22 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,10 +1,10 @@ import { Call, Pipe, Tuples } from "hotscript" import { AbstractClass, Opaque } from "type-fest" -import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "." +import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitClassFn, TraitImplClassFn, TraitImplInstanceFn, TraitInstanceFn } from "." import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" -class TraitsExpression< +class TraitExpression< Super extends AbstractClass, Traits extends readonly Trait[], > { @@ -42,9 +42,35 @@ class TraitsExpression< } } +type TraitExpressionOutput> = ( + Exp extends TraitExpression + ? ( + AbstractClass< + Pipe<[ + InstanceType, + ...Call, Traits>, + ], [ + ExtendFn, + SimplifyFn, + ]>, -export type Implements> = ( - Exp extends TraitsExpression + ConstructorParameters + > & + + Pipe<[ + Super, + ...Call, Traits>, + ], [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) + : never +) + +export type Implements> = ( + Exp extends TraitExpression ? Pipe, ExtendFn, @@ -61,7 +87,7 @@ export function extendsAndExpresses< superclass: Super, ...traits: Traits ) { - return new TraitsExpression(superclass, traits) + return new TraitExpression(superclass, traits) } class DefaultSuperclass {} @@ -71,5 +97,5 @@ export function expresses< >( ...traits: Traits ) { - return new TraitsExpression(DefaultSuperclass, traits) + return new TraitExpression(DefaultSuperclass, traits) } diff --git a/src/tests.ts b/src/tests.ts index 965715b..b5ca906 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,6 @@ -import { Implements, TraitAbstractMembers, expresses, extendsAndExpresses, trait } from "." +import { Booleans, Call, Compose, ComposeLeft, Match, Pipe, Tuples } from "hotscript" +import { Implements, TraitAbstractMembers, TraitAbstractMembersFn, expresses, extendsAndExpresses, trait } from "." +import { CheckExtendableFn, ExtendFn, Extendable, ExtendableFn, SimplifyFn } from "./util" const PrintsHelloOnNew = trait()(Super => @@ -52,7 +54,11 @@ const exp = extendsAndExpresses( Identifiable(), // Identifiable() ) -type Impl = Implements +type ExpImpl = Implements +type ExpAbstractMembers = Pipe, +]> +type ExpExtendable = Extendable class User extends exp.extends() implements Implements { id: bigint = -1n diff --git a/src/util/extend.ts b/src/util/extend.ts index c36ae4e..4639319 100644 --- a/src/util/extend.ts +++ b/src/util/extend.ts @@ -1,4 +1,4 @@ -import { Call, Fn, Tuples } from "hotscript" +import { Call, ComposeLeft, Fn, Match, Tuples } from "hotscript" type CommonKeys = Extract @@ -14,3 +14,13 @@ interface ExtendReducerFn extends Fn { export type ExtendFn = Tuples.Reduce export type Extend = Call + + +export type ExtendableFn = ComposeLeft<[ + ExtendFn, + Match<[ + Match.With, + Match.With, + ]> +]> +export type Extendable = Call -- 2.49.1 From 288969a7893a18b4f944f724069d017c51e3b38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 1 Feb 2024 03:41:18 +0100 Subject: [PATCH 18/65] Working expresses --- src/expresses.ts | 90 ++++++++++++++++++++++++++++++------------------ src/tests.ts | 13 +++---- src/trait.ts | 24 ++++++------- 3 files changed, 72 insertions(+), 55 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 5b9ed22..c66c0b9 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,7 +1,7 @@ -import { Call, Pipe, Tuples } from "hotscript" +import { Call, ComposeLeft, Pipe, Tuples } from "hotscript" import { AbstractClass, Opaque } from "type-fest" -import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitClassFn, TraitImplClassFn, TraitImplInstanceFn, TraitInstanceFn } from "." -import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" +import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "." +import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" class TraitExpression< @@ -42,33 +42,6 @@ class TraitExpression< } } -type TraitExpressionOutput> = ( - Exp extends TraitExpression - ? ( - AbstractClass< - Pipe<[ - InstanceType, - ...Call, Traits>, - ], [ - ExtendFn, - SimplifyFn, - ]>, - - ConstructorParameters - > & - - Pipe<[ - Super, - ...Call, Traits>, - ], [ - Tuples.Map, - ExtendFn, - SimplifyFn, - ]> - ) - : never -) - export type Implements> = ( Exp extends TraitExpression ? Pipe> = ( ) +type AbstractMembersExtendable< + Super extends AbstractClass, + Traits extends readonly Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplInstanceExtendable< + Super extends AbstractClass, + Traits extends readonly Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplStaticMembersExtendable< + Super extends AbstractClass, + Traits extends readonly Trait[], +> = ( + Call, + ...Call< + Tuples.Map< + ComposeLeft<[TraitImplClassFn, StaticMembersFn]> + >, + Traits + >, + ]> +) + + +type ExtendsAndExpressesReturnType< + Super extends AbstractClass, + Traits extends readonly Trait[], +> = ( + AbstractMembersExtendable extends true ? + ImplInstanceExtendable extends true ? + ImplStaticMembersExtendable extends true ? + TraitExpression + : "Type conflict between the traits implementation static members and/or the superclass static members." + : "Type conflict between the traits implementation instances and/or the superclass instance." + : "Type conflict between the traits abstract members and/or the superclass instance." +) + export function extendsAndExpresses< Super extends AbstractClass, Traits extends readonly Trait[], >( superclass: Super, ...traits: Traits -) { - return new TraitExpression(superclass, traits) +): ExtendsAndExpressesReturnType { + return new TraitExpression(superclass, traits) as any } class DefaultSuperclass {} @@ -96,6 +118,6 @@ export function expresses< Traits extends readonly Trait[], >( ...traits: Traits -) { - return new TraitExpression(DefaultSuperclass, traits) +): ExtendsAndExpressesReturnType { + return new TraitExpression(DefaultSuperclass, traits) as any } diff --git a/src/tests.ts b/src/tests.ts index b5ca906..2555515 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,6 +1,4 @@ -import { Booleans, Call, Compose, ComposeLeft, Match, Pipe, Tuples } from "hotscript" -import { Implements, TraitAbstractMembers, TraitAbstractMembersFn, expresses, extendsAndExpresses, trait } from "." -import { CheckExtendableFn, ExtendFn, Extendable, ExtendableFn, SimplifyFn } from "./util" +import { Implements, TraitAbstractMembers, extendsAndExpresses, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -45,7 +43,8 @@ const ActiveStatefulSubscription = trait(), // Identifiable() ) -type ExpImpl = Implements -type ExpAbstractMembers = Pipe, -]> -type ExpExtendable = Extendable +// type ExpImpl = ImplStaticMembersExtendable class User extends exp.extends() implements Implements { id: bigint = -1n diff --git a/src/trait.ts b/src/trait.ts index a8b758e..df897c3 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -3,16 +3,16 @@ import { AbstractClass, Class, Opaque } from "type-fest" import { StaticMembers } from "./util" -type AddAbstractMembersToImpl< - Impl extends Class, - AbstractMembers extends object, -> = ( - Class< - InstanceType & AbstractMembers, - ConstructorParameters - > & - StaticMembers -) +// type AddAbstractMembersToImpl< +// Impl extends Class, +// AbstractMembers extends object, +// > = ( +// Class< +// InstanceType & AbstractMembers, +// ConstructorParameters +// > & +// StaticMembers +// ) type RemoveAbstractMembersFromImplInstance< ImplInstanceWithAbstractMembers extends AbstractMembers, @@ -21,7 +21,7 @@ type RemoveAbstractMembersFromImplInstance< Omit ) -type RemoveAbstractMembersFromImpl< +type RemoveAbstractMembersFromImplClass< ImplWithAbstractMembers extends Class, AbstractMembers extends object, > = ( @@ -63,7 +63,7 @@ export interface TraitAbstractMembersFn extends Fn { export type TraitImplClass = ( T extends Trait - ? RemoveAbstractMembersFromImpl< + ? RemoveAbstractMembersFromImplClass< ImplWithAbstractMembers, AbstractMembers > -- 2.49.1 From 2945cdb7ae330fd3e3c420c0b2d7ae768e4e6ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 1 Feb 2024 03:51:07 +0100 Subject: [PATCH 19/65] Expresses fix --- src/expresses.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index c66c0b9..f439dc3 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,7 +1,7 @@ -import { Call, ComposeLeft, Pipe, Tuples } from "hotscript" +import { Call, Pipe, Tuples } from "hotscript" import { AbstractClass, Opaque } from "type-fest" import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "." -import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" +import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" class TraitExpression< @@ -77,14 +77,12 @@ type ImplStaticMembersExtendable< Super extends AbstractClass, Traits extends readonly Trait[], > = ( - Call, - ...Call< - Tuples.Map< - ComposeLeft<[TraitImplClassFn, StaticMembersFn]> - >, - Traits - >, + Pipe<[ + Super, + ...Call, Traits>, + ], [ + Tuples.Map, + ExtendableFn, ]> ) -- 2.49.1 From 7eb2b950a808c9be332868fe7b9ea4d8e5f4c34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 1 Feb 2024 04:09:52 +0100 Subject: [PATCH 20/65] Detect empty trait arrays --- src/expresses.ts | 6 ++++++ src/tests.ts | 13 +++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index f439dc3..8f2d4dd 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -13,6 +13,10 @@ class TraitExpression< readonly traits: Traits, ) {} + then(fn: (e: this) => V): V { + return fn(this) + } + extends(): ( AbstractClass< Pipe<[ @@ -91,6 +95,7 @@ type ExtendsAndExpressesReturnType< Super extends AbstractClass, Traits extends readonly Trait[], > = ( + Call extends false ? AbstractMembersExtendable extends true ? ImplInstanceExtendable extends true ? ImplStaticMembersExtendable extends true ? @@ -98,6 +103,7 @@ type ExtendsAndExpressesReturnType< : "Type conflict between the traits implementation static members and/or the superclass static members." : "Type conflict between the traits implementation instances and/or the superclass instance." : "Type conflict between the traits abstract members and/or the superclass instance." + : "Cannot express an empty list of traits." ) export function extendsAndExpresses< diff --git a/src/tests.ts b/src/tests.ts index 2555515..b94dbe6 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -48,15 +48,16 @@ class TestSuperclass { } -const exp = extendsAndExpresses( +const User = extendsAndExpresses( TestSuperclass, Identifiable(), // Identifiable() +).then(e => + class User + extends e.extends() + implements Implements { + id: bigint = -1n + } ) -// type ExpImpl = ImplStaticMembersExtendable - -class User extends exp.extends() implements Implements { - id: bigint = -1n -} new User().id -- 2.49.1 From 48f5f44d8f45b042301d630618569da9501d058c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 1 Feb 2024 04:11:53 +0100 Subject: [PATCH 21/65] Tests --- src/tests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tests.ts b/src/tests.ts index b94dbe6..597685e 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -50,6 +50,7 @@ class TestSuperclass { const User = extendsAndExpresses( TestSuperclass, + PrintsHelloOnNew, Identifiable(), // Identifiable() ).then(e => @@ -60,4 +61,4 @@ const User = extendsAndExpresses( } ) -new User().id +console.log(new User()) -- 2.49.1 From 939772c89cf0ddb78459ca4ec89fa616fd9bd473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 1 Feb 2024 05:18:35 +0100 Subject: [PATCH 22/65] Cleanup --- src/util/class.ts | 56 ----------------------------------------------- 1 file changed, 56 deletions(-) diff --git a/src/util/class.ts b/src/util/class.ts index d8030d7..45215e0 100644 --- a/src/util/class.ts +++ b/src/util/class.ts @@ -2,34 +2,6 @@ import { Fn } from "hotscript" import { AbstractClass } from "type-fest" -/** - * Represents an array of instances corresponding to the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesInstances[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? [InstanceType, ...ClassesInstances] - : never - : never - : [] -) - -/** - * Represents an intersection of instances of the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesInstancesIntersection[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? InstanceType & ClassesInstancesIntersection - : never - : never - : {} -) - /** * Represents the static members of a class. * @template Class - A class extending AbstractClass. @@ -41,31 +13,3 @@ export type StaticMembers> = ( export interface StaticMembersFn extends Fn { return: StaticMembers } - -/** - * Represents an array of static members corresponding to the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesStaticMembers[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? [StaticMembers, ...ClassesStaticMembers] - : never - : never - : [] -) - -/** - * Represents an intersection of static members of the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesStaticMembersIntersection[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? StaticMembers & ClassesStaticMembersIntersection - : never - : never - : {} -) -- 2.49.1 From 01d59f2cef6c2f7e445168cfdfb36f347cb12672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 2 Feb 2024 03:27:47 +0100 Subject: [PATCH 23/65] ExtendsAndExpressesReturnType refactoring --- src/expresses.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 8f2d4dd..ef25033 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -95,15 +95,15 @@ type ExtendsAndExpressesReturnType< Super extends AbstractClass, Traits extends readonly Trait[], > = ( - Call extends false ? - AbstractMembersExtendable extends true ? - ImplInstanceExtendable extends true ? - ImplStaticMembersExtendable extends true ? - TraitExpression - : "Type conflict between the traits implementation static members and/or the superclass static members." - : "Type conflict between the traits implementation instances and/or the superclass instance." - : "Type conflict between the traits abstract members and/or the superclass instance." - : "Cannot express an empty list of traits." + Call extends true + ? "Cannot express an empty list of traits." + : AbstractMembersExtendable extends false + ? "Type conflict between the traits abstract members and/or the superclass instance." + : ImplInstanceExtendable extends false + ? "Type conflict between the traits implementation instances and/or the superclass instance." + : ImplStaticMembersExtendable extends false + ? "Type conflict between the traits implementation static members and/or the superclass static members." + : TraitExpression ) export function extendsAndExpresses< -- 2.49.1 From 29148cd42b29a7b6d945bb320c27160a54daad67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 2 Feb 2024 05:10:28 +0100 Subject: [PATCH 24/65] Refactoring --- src/expresses.ts | 64 +++++++++++++++++++++++++++++++++--------------- src/tests.ts | 32 +++++++++++++----------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index ef25033..429629c 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -13,8 +13,8 @@ class TraitExpression< readonly traits: Traits, ) {} - then(fn: (e: this) => V): V { - return fn(this) + get implements() { + return {} } extends(): ( @@ -57,6 +57,44 @@ export type Implements> = ( ) +class TraitExpressionBuilder< + Super extends AbstractClass, + Traits extends readonly Trait[], +> { + constructor(public expression: TraitExpression) {} + + extends< + NewSuper extends AbstractClass + >(superclass: NewSuper) { + return new TraitExpressionBuilder( + new TraitExpression( + superclass, + this.expression.traits, + ) + ) + } + + expresses< + AppendTraits extends readonly Trait[] + >(...traits: AppendTraits) { + return new TraitExpressionBuilder( + new TraitExpression( + this.expression.superclass, + [...this.expression.traits, ...traits] as const, + ) + ) + } + + get() { + return this.expression as GetTraitExpression + } + + then(fn: (expression: typeof this.expression) => V): V { + return fn(this.expression) + } +} + + type AbstractMembersExtendable< Super extends AbstractClass, Traits extends readonly Trait[], @@ -90,8 +128,7 @@ type ImplStaticMembersExtendable< ]> ) - -type ExtendsAndExpressesReturnType< +type GetTraitExpression< Super extends AbstractClass, Traits extends readonly Trait[], > = ( @@ -106,22 +143,9 @@ type ExtendsAndExpressesReturnType< : TraitExpression ) -export function extendsAndExpresses< - Super extends AbstractClass, - Traits extends readonly Trait[], ->( - superclass: Super, - ...traits: Traits -): ExtendsAndExpressesReturnType { - return new TraitExpression(superclass, traits) as any -} class DefaultSuperclass {} -export function expresses< - Traits extends readonly Trait[], ->( - ...traits: Traits -): ExtendsAndExpressesReturnType { - return new TraitExpression(DefaultSuperclass, traits) as any -} +export const expression = new TraitExpressionBuilder( + new TraitExpression(DefaultSuperclass, [] as const) +) diff --git a/src/tests.ts b/src/tests.ts index 597685e..cd7e8a7 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, TraitAbstractMembers, extendsAndExpresses, trait } from "." +import { Implements, TraitAbstractMembers, expression, trait } from "." const PrintsHelloOnNew = trait()(Super => @@ -44,21 +44,25 @@ const ActiveStatefulSubscription = trait(), - // Identifiable() -).then(e => - class User - extends e.extends() - implements Implements { - id: bigint = -1n - } -) +const builder = expression + .extends(TestSuperclass) + .expresses( + // PrintsHelloOnNew, + Identifiable(), + // Identifiable(), + ) + +type Impl = Implements + + +const exp = builder.get() + +class User extends exp.extends() implements (typeof exp.implements) { + // id: bigint = -1n +} console.log(new User()) -- 2.49.1 From 7a449c73ccc798425d7534d61983c4a3c65411ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 2 Feb 2024 05:44:09 +0100 Subject: [PATCH 25/65] Fixed error detection --- src/expresses.ts | 30 ++++++++++++++++++------------ src/tests.ts | 8 +++----- src/util/extend.ts | 4 ++-- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 429629c..edb6428 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -6,18 +6,24 @@ import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" class TraitExpression< Super extends AbstractClass, - Traits extends readonly Trait[], + Traits extends Trait[], > { constructor( readonly superclass: Super, readonly traits: Traits, ) {} - get implements() { - return {} + get implements(): ( + Pipe, + ExtendFn, + SimplifyFn, + ]> + ) { + throw new Error("Not meant to be called") } - extends(): ( + get extends(): ( AbstractClass< Pipe<[ InstanceType, @@ -59,7 +65,7 @@ export type Implements> = ( class TraitExpressionBuilder< Super extends AbstractClass, - Traits extends readonly Trait[], + Traits extends Trait[], > { constructor(public expression: TraitExpression) {} @@ -75,7 +81,7 @@ class TraitExpressionBuilder< } expresses< - AppendTraits extends readonly Trait[] + AppendTraits extends Trait[] >(...traits: AppendTraits) { return new TraitExpressionBuilder( new TraitExpression( @@ -89,15 +95,15 @@ class TraitExpressionBuilder< return this.expression as GetTraitExpression } - then(fn: (expression: typeof this.expression) => V): V { - return fn(this.expression) + then(fn: (expression: ReturnType) => V): V { + return fn(this.get()) } } type AbstractMembersExtendable< Super extends AbstractClass, - Traits extends readonly Trait[], + Traits extends Trait[], > = ( Call, @@ -107,7 +113,7 @@ type AbstractMembersExtendable< type ImplInstanceExtendable< Super extends AbstractClass, - Traits extends readonly Trait[], + Traits extends Trait[], > = ( Call, @@ -117,7 +123,7 @@ type ImplInstanceExtendable< type ImplStaticMembersExtendable< Super extends AbstractClass, - Traits extends readonly Trait[], + Traits extends Trait[], > = ( Pipe<[ Super, @@ -130,7 +136,7 @@ type ImplStaticMembersExtendable< type GetTraitExpression< Super extends AbstractClass, - Traits extends readonly Trait[], + Traits extends Trait[], > = ( Call extends true ? "Cannot express an empty list of traits." diff --git a/src/tests.ts b/src/tests.ts index cd7e8a7..ac36276 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,3 +1,4 @@ +import { Identity, Pipe, Tuples } from "hotscript" import { Implements, TraitAbstractMembers, expression, trait } from "." @@ -51,17 +52,14 @@ class TestSuperclass { const builder = expression .extends(TestSuperclass) .expresses( - // PrintsHelloOnNew, + PrintsHelloOnNew, Identifiable(), // Identifiable(), ) -type Impl = Implements - - const exp = builder.get() -class User extends exp.extends() implements (typeof exp.implements) { +class User extends exp.extends implements (typeof exp.implements) { // id: bigint = -1n } diff --git a/src/util/extend.ts b/src/util/extend.ts index 4639319..a7ee625 100644 --- a/src/util/extend.ts +++ b/src/util/extend.ts @@ -13,7 +13,7 @@ interface ExtendReducerFn extends Fn { } export type ExtendFn = Tuples.Reduce -export type Extend = Call +export type Extend = Call export type ExtendableFn = ComposeLeft<[ @@ -23,4 +23,4 @@ export type ExtendableFn = ComposeLeft<[ Match.With, ]> ]> -export type Extendable = Call +export type Extendable = Call -- 2.49.1 From 58de52ffc062a1414c941b0f280766b6bd7f93b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 2 Feb 2024 20:14:44 +0100 Subject: [PATCH 26/65] Fix --- src/expresses.ts | 10 ---------- src/tests.ts | 8 ++------ 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index edb6428..ecdcf4e 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -13,16 +13,6 @@ class TraitExpression< readonly traits: Traits, ) {} - get implements(): ( - Pipe, - ExtendFn, - SimplifyFn, - ]> - ) { - throw new Error("Not meant to be called") - } - get extends(): ( AbstractClass< Pipe<[ diff --git a/src/tests.ts b/src/tests.ts index ac36276..c8b2aeb 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,3 @@ -import { Identity, Pipe, Tuples } from "hotscript" import { Implements, TraitAbstractMembers, expression, trait } from "." @@ -40,9 +39,6 @@ const ActiveStatefulSubscription = trait> - - class TestSuperclass { // id: number = 69 // static test = 69 @@ -59,8 +55,8 @@ const builder = expression const exp = builder.get() -class User extends exp.extends implements (typeof exp.implements) { - // id: bigint = -1n +class User extends exp.extends implements Implements { + id: bigint = -1n } console.log(new User()) -- 2.49.1 From acc26c7e0cb8f2007a3356851cfc3383d492ce31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 2 Feb 2024 22:42:45 +0100 Subject: [PATCH 27/65] Subtrait work --- src/abstract.ts | 8 ++++++++ src/expresses.ts | 30 ++++++++++++++++++++++++++++-- src/index.ts | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/abstract.ts diff --git a/src/abstract.ts b/src/abstract.ts new file mode 100644 index 0000000..ee9dc5e --- /dev/null +++ b/src/abstract.ts @@ -0,0 +1,8 @@ +import { Opaque } from "type-fest" + + +export type AbstractTag = "@thilawyn/traitify-ts/Abstract" + +export function abstract() { + return {} as Opaque +} diff --git a/src/expresses.ts b/src/expresses.ts index ecdcf4e..5b67030 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -1,9 +1,19 @@ import { Call, Pipe, Tuples } from "hotscript" -import { AbstractClass, Opaque } from "type-fest" -import { Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "." +import { AbstractClass, Class, Opaque } from "type-fest" +import { AbstractTag, Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "." import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" +type SubtraitApplier< + Traits extends Trait[], + Abstract extends object, + ImplWithAbstract extends Class, +> = ( + (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ) +) + class TraitExpression< Super extends AbstractClass, Traits extends Trait[], @@ -40,6 +50,22 @@ class TraitExpression< this.superclass as Opaque, ) as any } + + subtrait< + SubtraitAbstract extends object, + SubtraitImpl extends Class, + >( + abstract: ( + abstract: Pipe, + SimplifyFn, + ]> + ) => Opaque, + + // impl: () + ) { + + } } export type Implements> = ( diff --git a/src/index.ts b/src/index.ts index ae86066..b839462 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,3 @@ +export * from "./abstract" export * from "./expresses" export * from "./trait" -- 2.49.1 From a061bac1de4fdb42caf72d550b73aa9edfb6d85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 01:09:40 +0100 Subject: [PATCH 28/65] Trait refactoring --- src/tests.ts | 1 + src/trait.ts | 76 +++++++++++++++++++++++++--------------------------- 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index c8b2aeb..cc7f851 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -54,6 +54,7 @@ const builder = expression ) const exp = builder.get() +type Abs = Implements class User extends exp.extends implements Implements { id: bigint = -1n diff --git a/src/trait.ts b/src/trait.ts index df897c3..37951c2 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -3,30 +3,30 @@ import { AbstractClass, Class, Opaque } from "type-fest" import { StaticMembers } from "./util" -// type AddAbstractMembersToImpl< -// Impl extends Class, -// AbstractMembers extends object, -// > = ( -// Class< -// InstanceType & AbstractMembers, -// ConstructorParameters -// > & -// StaticMembers -// ) +type AddAbstractToImplClass< + Impl extends Class, + Abstract extends object, +> = ( + Class< + InstanceType & Abstract, + ConstructorParameters + > & + StaticMembers +) -type RemoveAbstractMembersFromImplInstance< +type RemoveAbstractFromImplInstance< ImplInstanceWithAbstractMembers extends AbstractMembers, AbstractMembers extends object, > = ( Omit ) -type RemoveAbstractMembersFromImplClass< +type RemoveAbstractFromImplClass< ImplWithAbstractMembers extends Class, AbstractMembers extends object, > = ( Class< - RemoveAbstractMembersFromImplInstance< + RemoveAbstractFromImplInstance< InstanceType, AbstractMembers >, @@ -40,13 +40,13 @@ type RemoveAbstractMembersFromImplClass< export type TraitTag = "@thilawyn/traitify-ts/Trait" export type Trait< - AbstractMembers extends object, - ImplWithAbstractMembers extends Class, + Abstract extends object, + Impl extends Class, > = ( Opaque<{ readonly apply: TraitApplier< - AbstractMembers, - ImplWithAbstractMembers + Abstract, + AddAbstractToImplClass > }, TraitTag> ) @@ -62,11 +62,8 @@ export interface TraitAbstractMembersFn extends Fn { } export type TraitImplClass = ( - T extends Trait - ? RemoveAbstractMembersFromImplClass< - ImplWithAbstractMembers, - AbstractMembers - > + T extends Trait + ? Impl : never ) @@ -75,11 +72,8 @@ export interface TraitImplClassFn extends Fn { } export type TraitImplInstance = ( - T extends Trait - ? RemoveAbstractMembersFromImplInstance< - InstanceType, - AbstractMembers - > + T extends Trait + ? InstanceType : never ) @@ -88,8 +82,8 @@ export interface TraitImplInstanceFn extends Fn { } export type TraitClass = ( - T extends Trait - ? ImplWithAbstractMembers + T extends Trait + ? AddAbstractToImplClass : never ) @@ -98,8 +92,10 @@ export interface TraitClassFn extends Fn { } export type TraitInstance = ( - T extends Trait - ? InstanceType + T extends Trait + ? InstanceType< + AddAbstractToImplClass + > : never ) @@ -111,22 +107,22 @@ export interface TraitInstanceFn extends Fn { export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" export type TraitApplier< - AbstractMembers extends object, - ImplWithAbstractMembers extends Class, + Abstract extends object, + ImplWithAbstract extends Class, > = ( - (Super: Opaque, TraitApplierSuperTag>) => ( - Opaque + (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque ) ) export function trait< - AbstractMembers extends object = {} + Abstract extends object = {} >(): ( - >( - apply: TraitApplier + >( + apply: TraitApplier ) => Trait< - AbstractMembers, - ImplWithAbstractMembers + Abstract, + RemoveAbstractFromImplClass > ) { return apply => ({ apply }) as any -- 2.49.1 From 3c40a0a96bd7fede20ed9e473a5c0c037b2f6e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 01:30:20 +0100 Subject: [PATCH 29/65] Fix --- src/trait.ts | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/trait.ts b/src/trait.ts index 37951c2..6309935 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -3,7 +3,7 @@ import { AbstractClass, Class, Opaque } from "type-fest" import { StaticMembers } from "./util" -type AddAbstractToImplClass< +type AddAbstractToImpl< Impl extends Class, Abstract extends object, > = ( @@ -14,26 +14,15 @@ type AddAbstractToImplClass< StaticMembers ) -type RemoveAbstractFromImplInstance< - ImplInstanceWithAbstractMembers extends AbstractMembers, - AbstractMembers extends object, -> = ( - Omit -) - -type RemoveAbstractFromImplClass< - ImplWithAbstractMembers extends Class, - AbstractMembers extends object, +type RemoveAbstractFromImpl< + ImplWithAbstract extends Class, + Abstract extends object, > = ( Class< - RemoveAbstractFromImplInstance< - InstanceType, - AbstractMembers - >, - - ConstructorParameters + Omit, keyof Abstract>, + ConstructorParameters > & - StaticMembers + StaticMembers ) @@ -46,7 +35,7 @@ export type Trait< Opaque<{ readonly apply: TraitApplier< Abstract, - AddAbstractToImplClass + AddAbstractToImpl > }, TraitTag> ) @@ -83,7 +72,7 @@ export interface TraitImplInstanceFn extends Fn { export type TraitClass = ( T extends Trait - ? AddAbstractToImplClass + ? AddAbstractToImpl : never ) @@ -94,7 +83,7 @@ export interface TraitClassFn extends Fn { export type TraitInstance = ( T extends Trait ? InstanceType< - AddAbstractToImplClass + AddAbstractToImpl > : never ) @@ -122,7 +111,7 @@ export function trait< apply: TraitApplier ) => Trait< Abstract, - RemoveAbstractFromImplClass + RemoveAbstractFromImpl > ) { return apply => ({ apply }) as any -- 2.49.1 From c1097ff2f2374e7fb6e7fbd49344dc8d7b0a0deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 02:18:36 +0100 Subject: [PATCH 30/65] Trait refactoring --- src/abstract.ts | 8 ++++++-- src/tests.ts | 45 ++++++++++++++++++++++++--------------------- src/trait.ts | 23 +++++++++++++---------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/abstract.ts b/src/abstract.ts index ee9dc5e..bfe4987 100644 --- a/src/abstract.ts +++ b/src/abstract.ts @@ -3,6 +3,10 @@ import { Opaque } from "type-fest" export type AbstractTag = "@thilawyn/traitify-ts/Abstract" -export function abstract() { - return {} as Opaque +export function abstract< + Abstract extends {} = {} +>(): ( + Opaque +) { + return undefined as any } diff --git a/src/tests.ts b/src/tests.ts index cc7f851..ffb6a18 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,41 +1,44 @@ -import { Implements, TraitAbstractMembers, expression, trait } from "." +import { Implements, TraitAbstractMembers, abstract, expression, trait } from "." -const PrintsHelloOnNew = trait()(Super => - class PrintsHelloOnNew extends Super { +const PrintsHelloOnNew = trait( + abstract(), + Super => class PrintsHelloOnNew extends Super { constructor(...args: any[]) { super(...args) console.log("Hello!") } - } + }, ) -const Identifiable = () => ( - trait<{ readonly id: ID }>()(Super => - class Identifiable extends Super { - equals(el: Identifiable) { - return this.id === el.id - } +const Identifiable = () => trait( + abstract<{ readonly id: ID }>(), + Super => class Identifiable extends Super { + equals(el: Identifiable) { + return this.id === el.id } - ) + }, ) -const StatefulSubscription = trait<{ - readonly status: ( - { _tag: "awaitingPayment" } | - { _tag: "active", activeSince: Date, expiresAt?: Date } | - { _tag: "expired", expiredSince: Date } - ) -}>()(Super => - class StatefulSubscription extends Super {} +const StatefulSubscription = trait( + abstract<{ + readonly status: ( + { _tag: "awaitingPayment" } | + { _tag: "active", activeSince: Date, expiresAt?: Date } | + { _tag: "expired", expiredSince: Date } + ) + }>(), + + Super => class StatefulSubscription extends Super {}, ) interface ActiveStatefulSubscriptionAbstractMembers extends TraitAbstractMembers { readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } } -const ActiveStatefulSubscription = trait()(Super => - class ActiveStatefulSubscription extends Super {} +const ActiveStatefulSubscription = trait( + abstract(), + Super => class ActiveStatefulSubscription extends Super {}, ) diff --git a/src/trait.ts b/src/trait.ts index 6309935..6d5e5fc 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,6 +1,7 @@ import { Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" import { StaticMembers } from "./util" +import { AbstractTag } from "." type AddAbstractToImpl< @@ -105,14 +106,16 @@ export type TraitApplier< ) export function trait< - Abstract extends object = {} ->(): ( - >( - apply: TraitApplier - ) => Trait< - Abstract, - RemoveAbstractFromImpl - > -) { - return apply => ({ apply }) as any + Abstract extends {}, + ImplWithAbstract extends Class, +>( + abstract: Opaque, + apply: (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ), +): Trait< + Abstract, + RemoveAbstractFromImpl +> { + return { apply } as any } -- 2.49.1 From c04405181352801222a0f308ca5928486ba55709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 02:21:04 +0100 Subject: [PATCH 31/65] Fix --- src/abstract.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/abstract.ts b/src/abstract.ts index bfe4987..1cf2562 100644 --- a/src/abstract.ts +++ b/src/abstract.ts @@ -5,8 +5,6 @@ export type AbstractTag = "@thilawyn/traitify-ts/Abstract" export function abstract< Abstract extends {} = {} ->(): ( - Opaque -) { +>(): Opaque { return undefined as any } -- 2.49.1 From c6b9bbe9cb8c9421d58a22a70b8d4b81a1282fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 02:24:44 +0100 Subject: [PATCH 32/65] Fix --- src/trait.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/trait.ts b/src/trait.ts index 6d5e5fc..71dbaeb 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,7 +1,7 @@ import { Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { StaticMembers } from "./util" import { AbstractTag } from "." +import { StaticMembers } from "./util" type AddAbstractToImpl< @@ -97,7 +97,7 @@ export interface TraitInstanceFn extends Fn { export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" export type TraitApplier< - Abstract extends object, + Abstract extends {}, ImplWithAbstract extends Class, > = ( (Super: Opaque, TraitApplierSuperTag>) => ( @@ -109,10 +109,8 @@ export function trait< Abstract extends {}, ImplWithAbstract extends Class, >( - abstract: Opaque, - apply: (Super: Opaque, TraitApplierSuperTag>) => ( - Opaque - ), + abstract: Opaque, + apply: TraitApplier, ): Trait< Abstract, RemoveAbstractFromImpl -- 2.49.1 From be59a6e0eaca13505b6104faff4e96b1263d41b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 03:12:32 +0100 Subject: [PATCH 33/65] Subtrait work --- src/expresses.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 5b67030..2d715f2 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -52,8 +52,8 @@ class TraitExpression< } subtrait< - SubtraitAbstract extends object, - SubtraitImpl extends Class, + SubtraitAbstract extends object, + SubtraitImplWithAbstract extends Class, >( abstract: ( abstract: Pipe Date: Sat, 3 Feb 2024 03:22:14 +0100 Subject: [PATCH 34/65] Fix --- src/trait.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/trait.ts b/src/trait.ts index 71dbaeb..9560b83 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -5,8 +5,8 @@ import { StaticMembers } from "./util" type AddAbstractToImpl< - Impl extends Class, - Abstract extends object, + Impl extends Class<{}, []>, + Abstract extends {}, > = ( Class< InstanceType & Abstract, @@ -17,7 +17,7 @@ type AddAbstractToImpl< type RemoveAbstractFromImpl< ImplWithAbstract extends Class, - Abstract extends object, + Abstract extends {}, > = ( Class< Omit, keyof Abstract>, @@ -30,8 +30,8 @@ type RemoveAbstractFromImpl< export type TraitTag = "@thilawyn/traitify-ts/Trait" export type Trait< - Abstract extends object, - Impl extends Class, + Abstract extends {}, + Impl extends Class<{}, []>, > = ( Opaque<{ readonly apply: TraitApplier< -- 2.49.1 From bdfc57481d0b0ea515bb3cc8094bdae47942361d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 04:09:35 +0100 Subject: [PATCH 35/65] Refactoring --- src/expresses.ts | 26 +++++++---------------- src/trait.ts | 55 +++++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 2d715f2..785c844 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -4,18 +4,8 @@ import { AbstractTag, Trait, TraitAbstractMembersFn, TraitApplierSuperTag, Trait import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" -type SubtraitApplier< - Traits extends Trait[], - Abstract extends object, - ImplWithAbstract extends Class, -> = ( - (Super: Opaque, TraitApplierSuperTag>) => ( - Opaque - ) -) - class TraitExpression< - Super extends AbstractClass, + Super extends AbstractClass<{}>, Traits extends Trait[], > { constructor( @@ -52,8 +42,8 @@ class TraitExpression< } subtrait< - SubtraitAbstract extends object, - SubtraitImplWithAbstract extends Class, + SubtraitAbstract extends {}, + SubtraitImplWithAbstract extends Class<{}>, >( abstract: ( abstract: Pipe> = ( class TraitExpressionBuilder< - Super extends AbstractClass, + Super extends AbstractClass<{}>, Traits extends Trait[], > { constructor(public expression: TraitExpression) {} @@ -118,7 +108,7 @@ class TraitExpressionBuilder< type AbstractMembersExtendable< - Super extends AbstractClass, + Super extends AbstractClass<{}>, Traits extends Trait[], > = ( Call, + Super extends AbstractClass<{}>, Traits extends Trait[], > = ( Call, + Super extends AbstractClass<{}>, Traits extends Trait[], > = ( Pipe<[ @@ -151,7 +141,7 @@ type ImplStaticMembersExtendable< ) type GetTraitExpression< - Super extends AbstractClass, + Super extends AbstractClass<{}>, Traits extends Trait[], > = ( Call extends true diff --git a/src/trait.ts b/src/trait.ts index 9560b83..b51ec0f 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -27,19 +27,29 @@ type RemoveAbstractFromImpl< ) -export type TraitTag = "@thilawyn/traitify-ts/Trait" +// export type TraitTag = "@thilawyn/traitify-ts/Trait" -export type Trait< +// export type Trait< +// Abstract extends {}, +// Impl extends Class<{}, []>, +// > = ( +// Opaque<{ +// readonly apply: TraitApplier< +// Abstract, +// AddAbstractToImpl +// > +// }, TraitTag> +// ) + +export class Trait< Abstract extends {}, Impl extends Class<{}, []>, -> = ( - Opaque<{ - readonly apply: TraitApplier< - Abstract, - AddAbstractToImpl - > - }, TraitTag> -) +> { + constructor( + readonly abstract: Abstract, + readonly apply: (Super: AbstractClass<{}>) => Impl, + ) {} +} export type TraitAbstractMembers = ( T extends Trait @@ -96,24 +106,17 @@ export interface TraitInstanceFn extends Fn { export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" -export type TraitApplier< - Abstract extends {}, - ImplWithAbstract extends Class, -> = ( - (Super: Opaque, TraitApplierSuperTag>) => ( - Opaque - ) -) - export function trait< Abstract extends {}, ImplWithAbstract extends Class, >( - abstract: Opaque, - apply: TraitApplier, -): Trait< - Abstract, - RemoveAbstractFromImpl -> { - return { apply } as any + abstract: Opaque, + apply: (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ), +) { + return new Trait( + abstract as Abstract, + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImpl, + ) } -- 2.49.1 From 8af604831bf34a079572606f8d083d144c578673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 04:18:31 +0100 Subject: [PATCH 36/65] Cleanup --- src/trait.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/trait.ts b/src/trait.ts index b51ec0f..e5608cb 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -27,20 +27,6 @@ type RemoveAbstractFromImpl< ) -// export type TraitTag = "@thilawyn/traitify-ts/Trait" - -// export type Trait< -// Abstract extends {}, -// Impl extends Class<{}, []>, -// > = ( -// Opaque<{ -// readonly apply: TraitApplier< -// Abstract, -// AddAbstractToImpl -// > -// }, TraitTag> -// ) - export class Trait< Abstract extends {}, Impl extends Class<{}, []>, -- 2.49.1 From 0d469fabebd8526ad954ef21f9c1cd671d4d2a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 23:15:30 +0100 Subject: [PATCH 37/65] Trait refactoring --- src/abstract.ts | 4 ++-- src/trait.ts | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/abstract.ts b/src/abstract.ts index 1cf2562..c6502e4 100644 --- a/src/abstract.ts +++ b/src/abstract.ts @@ -5,6 +5,6 @@ export type AbstractTag = "@thilawyn/traitify-ts/Abstract" export function abstract< Abstract extends {} = {} ->(): Opaque { - return undefined as any +>() { + return {} as Opaque } diff --git a/src/trait.ts b/src/trait.ts index e5608cb..6ae2eaf 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -28,17 +28,27 @@ type RemoveAbstractFromImpl< export class Trait< - Abstract extends {}, - Impl extends Class<{}, []>, + Abstract extends {}, + Impl extends Class<{}, []>, + Supertraits extends Trait[] > { constructor( - readonly abstract: Abstract, - readonly apply: (Super: AbstractClass<{}>) => Impl, + readonly supertraits: Supertraits, + readonly ownAbstract: Abstract, + readonly apply: (Super: AbstractClass<{}>) => Impl, ) {} } +export interface Trait< + Abstract extends {}, + Impl extends Class<{}, []>, + Supertraits extends Trait[] +> { + get ownImplClass(): Impl +} + export type TraitAbstractMembers = ( - T extends Trait + T extends Trait ? AbstractMembers : never ) @@ -48,7 +58,7 @@ export interface TraitAbstractMembersFn extends Fn { } export type TraitImplClass = ( - T extends Trait + T extends Trait ? Impl : never ) @@ -102,6 +112,7 @@ export function trait< ), ) { return new Trait( + [] as const, abstract as Abstract, apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImpl, ) -- 2.49.1 From 8d29d9ba949b76ee5ec462ff668c33dbafb4ddf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 3 Feb 2024 23:32:56 +0100 Subject: [PATCH 38/65] Fix --- src/expresses.ts | 4 ++-- src/trait.ts | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/expresses.ts b/src/expresses.ts index 785c844..53cb047 100644 --- a/src/expresses.ts +++ b/src/expresses.ts @@ -4,9 +4,9 @@ import { AbstractTag, Trait, TraitAbstractMembersFn, TraitApplierSuperTag, Trait import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" -class TraitExpression< +export class TraitExpression< Super extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > { constructor( readonly superclass: Super, diff --git a/src/trait.ts b/src/trait.ts index 6ae2eaf..c6eef90 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,6 +1,6 @@ import { Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag } from "." +import { AbstractTag, TraitExpression } from "." import { StaticMembers } from "./util" @@ -28,21 +28,21 @@ type RemoveAbstractFromImpl< export class Trait< - Abstract extends {}, - Impl extends Class<{}, []>, - Supertraits extends Trait[] + Super extends TraitExpression[], + Abstract extends {}, + Impl extends Class<{}, []>, > { constructor( - readonly supertraits: Supertraits, + readonly supertraits: Super, readonly ownAbstract: Abstract, readonly apply: (Super: AbstractClass<{}>) => Impl, ) {} } export interface Trait< + Super extends TraitExpression[], Abstract extends {}, Impl extends Class<{}, []>, - Supertraits extends Trait[] > { get ownImplClass(): Impl } -- 2.49.1 From 0ff6b7896e0e0ef31d990af5ae3cec1260485bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 00:26:09 +0100 Subject: [PATCH 39/65] Trait refactoring --- src/{expresses.ts => TraitExpression.ts} | 4 +- src/index.ts | 2 +- src/trait.ts | 109 +++++++++-------------- 3 files changed, 46 insertions(+), 69 deletions(-) rename src/{expresses.ts => TraitExpression.ts} (97%) diff --git a/src/expresses.ts b/src/TraitExpression.ts similarity index 97% rename from src/expresses.ts rename to src/TraitExpression.ts index 53cb047..31cc311 100644 --- a/src/expresses.ts +++ b/src/TraitExpression.ts @@ -156,8 +156,8 @@ type GetTraitExpression< ) -class DefaultSuperclass {} +export class NullTraitExpressionSuperclass {} export const expression = new TraitExpressionBuilder( - new TraitExpression(DefaultSuperclass, [] as const) + new TraitExpression(NullTraitExpressionSuperclass, [] as const) ) diff --git a/src/index.ts b/src/index.ts index b839462..b92ea0f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ +export * from "./TraitExpression" export * from "./abstract" -export * from "./expresses" export * from "./trait" diff --git a/src/trait.ts b/src/trait.ts index c6eef90..4d5ea36 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,119 +1,96 @@ -import { Fn } from "hotscript" +import { Call, Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, TraitExpression } from "." +import { AbstractTag, NullTraitExpressionSuperclass, TraitExpression } from "." import { StaticMembers } from "./util" -type AddAbstractToImpl< - Impl extends Class<{}, []>, - Abstract extends {}, +type AddAbstractToImplClass< + ImplClass extends Class<{}, []>, + Abstract extends {}, > = ( Class< - InstanceType & Abstract, - ConstructorParameters + InstanceType & Abstract, + ConstructorParameters > & - StaticMembers + StaticMembers ) -type RemoveAbstractFromImpl< - ImplWithAbstract extends Class, - Abstract extends {}, +type RemoveAbstractFromImplClass< + ImplClassWithAbstract extends Class, + Abstract extends {}, > = ( Class< - Omit, keyof Abstract>, - ConstructorParameters + Omit, keyof Abstract>, + ConstructorParameters > & - StaticMembers + StaticMembers ) export class Trait< - Super extends TraitExpression[], + Super extends TraitExpression[], Abstract extends {}, - Impl extends Class<{}, []>, + ImplClass extends Class<{}, []>, > { constructor( - readonly supertraits: Super, - readonly ownAbstract: Abstract, - readonly apply: (Super: AbstractClass<{}>) => Impl, + readonly superExpression: Super, + readonly abstract: Abstract, + readonly apply: (Super: AbstractClass<{}>) => ImplClass, ) {} } -export interface Trait< - Super extends TraitExpression[], - Abstract extends {}, - Impl extends Class<{}, []>, -> { - get ownImplClass(): Impl -} - -export type TraitAbstractMembers = ( - T extends Trait - ? AbstractMembers +export interface TraitOwnAbstractFn extends Fn { + return: this["arg0"] extends Trait + ? Abstract : never -) - -export interface TraitAbstractMembersFn extends Fn { - return: TraitAbstractMembers } +export type TraitOwnAbstract = Call -export type TraitImplClass = ( - T extends Trait - ? Impl +export interface TraitOwnImplClassFn extends Fn { + return: this["arg0"] extends Trait + ? ImplClass : never -) - -export interface TraitImplClassFn extends Fn { - return: TraitImplClass } +export type TraitOwnImplClass = Call -export type TraitImplInstance = ( - T extends Trait - ? InstanceType +export interface TraitOwnImplInstanceFn extends Fn { + return: this["arg0"] extends Trait + ? InstanceType : never -) - -export interface TraitImplInstanceFn extends Fn { - return: TraitImplInstance } +export type TraitOwnImplInstance = Call -export type TraitClass = ( - T extends Trait - ? AddAbstractToImpl +export interface TraitOwnClassFn extends Fn { + return: this["arg0"] extends Trait + ? AddAbstractToImplClass : never -) - -export interface TraitClassFn extends Fn { - return: TraitClass } +export type TraitOwnClass = Call -export type TraitInstance = ( - T extends Trait +export interface TraitOwnInstanceFn extends Fn { + return: this["arg0"] extends Trait ? InstanceType< - AddAbstractToImpl + AddAbstractToImplClass > : never -) - -export interface TraitInstanceFn extends Fn { - return: TraitInstance } +export type TraitOwnInstance = Call export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" export function trait< - Abstract extends {}, - ImplWithAbstract extends Class, + Abstract extends {}, + ImplClassWithAbstract extends Class, >( abstract: Opaque, apply: (Super: Opaque, TraitApplierSuperTag>) => ( - Opaque + Opaque ), ) { return new Trait( [] as const, abstract as Abstract, - apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImpl, + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, ) } -- 2.49.1 From 1219cd7a8936cdc97a4d1bcec5f50bf2145c1e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 00:30:32 +0100 Subject: [PATCH 40/65] Fix --- src/TraitExpression.ts | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 31cc311..a069f95 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,6 +1,6 @@ import { Call, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "." +import { AbstractTag, Trait, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn } from "." import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" @@ -17,7 +17,7 @@ export class TraitExpression< AbstractClass< Pipe<[ InstanceType, - ...Call, Traits>, + ...Call, Traits>, ], [ ExtendFn, SimplifyFn, @@ -28,7 +28,7 @@ export class TraitExpression< Pipe<[ Super, - ...Call, Traits>, + ...Call, Traits>, ], [ Tuples.Map, ExtendFn, @@ -47,7 +47,7 @@ export class TraitExpression< >( abstract: ( abstract: Pipe, + Tuples.Map, SimplifyFn, ]> ) => Opaque, @@ -58,10 +58,12 @@ export class TraitExpression< } } + + export type Implements> = ( Exp extends TraitExpression ? Pipe, + Tuples.Map, ExtendFn, SimplifyFn, ]> @@ -71,7 +73,7 @@ export type Implements> = ( class TraitExpressionBuilder< Super extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > { constructor(public expression: TraitExpression) {} @@ -87,7 +89,7 @@ class TraitExpressionBuilder< } expresses< - AppendTraits extends Trait[] + AppendTraits extends Trait[] >(...traits: AppendTraits) { return new TraitExpressionBuilder( new TraitExpression( @@ -109,31 +111,31 @@ class TraitExpressionBuilder< type AbstractMembersExtendable< Super extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > = ( Call, - ...Call, Traits>, + ...Call, Traits>, ]> ) type ImplInstanceExtendable< Super extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > = ( Call, - ...Call, Traits>, + ...Call, Traits>, ]> ) type ImplStaticMembersExtendable< Super extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > = ( Pipe<[ Super, - ...Call, Traits>, + ...Call, Traits>, ], [ Tuples.Map, ExtendableFn, @@ -142,7 +144,7 @@ type ImplStaticMembersExtendable< type GetTraitExpression< Super extends AbstractClass<{}>, - Traits extends Trait[], + Traits extends Trait[], > = ( Call extends true ? "Cannot express an empty list of traits." -- 2.49.1 From ec914e0ffd71e947ba560ad757a90df285f8dc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 02:22:35 +0100 Subject: [PATCH 41/65] TraitExpressionTraitsFn --- src/TraitExpression.ts | 52 ++++++++++++++++++++++++++++++++++++------ src/tests.ts | 16 ++++++------- src/trait.ts | 26 +++++++++++++++++---- 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index a069f95..c0ea010 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,9 +1,11 @@ -import { Call, Pipe, Tuples } from "hotscript" +import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, Trait, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn } from "." +import { AbstractTag, Trait, TraitAbstractFn, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn } from "." import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" +export class TraitExpressionNullSuperclass {} + export class TraitExpression< Super extends AbstractClass<{}>, Traits extends Trait[], @@ -58,6 +60,46 @@ export class TraitExpression< } } +export const emptyTraitExpression = new TraitExpression(TraitExpressionNullSuperclass, [] as const) + +interface PrependTraitSupertraitsFn extends Fn { + return: [ + ...Call, + this["arg0"], + ] +} +export interface TraitExpressionTraitsFn extends Fn { + return: this["arg0"] extends TraitExpression + ? Call, Traits> + : never +} + +export interface TraitExpressionAbstractFn extends Fn { + return: this["arg0"] extends TraitExpression + ? Pipe + : never +} + +export interface TraitExpressionInstanceFn extends Fn { + return: this["arg0"] extends TraitExpression + ? Pipe + : never +} + +export interface TraitExpressionStaticFn extends Fn { + return: this["arg0"] extends TraitExpression + ? Pipe + : never +} export type Implements> = ( @@ -158,8 +200,4 @@ type GetTraitExpression< ) -export class NullTraitExpressionSuperclass {} - -export const expression = new TraitExpressionBuilder( - new TraitExpression(NullTraitExpressionSuperclass, [] as const) -) +export const expression = new TraitExpressionBuilder(emptyTraitExpression) diff --git a/src/tests.ts b/src/tests.ts index ffb6a18..710a660 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, TraitAbstractMembers, abstract, expression, trait } from "." +import { Implements, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( @@ -32,14 +32,14 @@ const StatefulSubscription = trait( Super => class StatefulSubscription extends Super {}, ) -interface ActiveStatefulSubscriptionAbstractMembers extends TraitAbstractMembers { - readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } -} +// interface ActiveStatefulSubscriptionAbstractMembers extends TraitAbstractMembers { +// readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } +// } -const ActiveStatefulSubscription = trait( - abstract(), - Super => class ActiveStatefulSubscription extends Super {}, -) +// const ActiveStatefulSubscription = trait( +// abstract(), +// Super => class ActiveStatefulSubscription extends Super {}, +// ) class TestSuperclass { diff --git a/src/trait.ts b/src/trait.ts index 4d5ea36..a028dc8 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,7 +1,7 @@ import { Call, Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, NullTraitExpressionSuperclass, TraitExpression } from "." -import { StaticMembers } from "./util" +import { AbstractTag, TraitExpression, TraitExpressionAbstractFn, TraitExpressionNullSuperclass, TraitExpressionTraitsFn, emptyTraitExpression } from "." +import { ExtendFn, StaticMembers } from "./util" type AddAbstractToImplClass< @@ -28,7 +28,7 @@ type RemoveAbstractFromImplClass< export class Trait< - Super extends TraitExpression[], + Super extends TraitExpression, Abstract extends {}, ImplClass extends Class<{}, []>, > { @@ -54,7 +54,7 @@ export interface TraitOwnImplClassFn extends Fn { export type TraitOwnImplClass = Call export interface TraitOwnImplInstanceFn extends Fn { - return: this["arg0"] extends Trait + return: this["arg0"] extends Trait ? InstanceType : never } @@ -77,6 +77,22 @@ export interface TraitOwnInstanceFn extends Fn { export type TraitOwnInstance = Call +export interface TraitSupertraitsFn extends Fn { + return: this["arg0"] extends Trait + ? Call + : never +} + +export interface TraitAbstractFn extends Fn { + return: this["arg0"] extends Trait + ? Call, + Abstract, + ]> + : never +} + + export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" export function trait< @@ -89,7 +105,7 @@ export function trait< ), ) { return new Trait( - [] as const, + emptyTraitExpression, abstract as Abstract, apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, ) -- 2.49.1 From 781567a3bd8035748a6173142151b2b21ac02c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 02:53:47 +0100 Subject: [PATCH 42/65] TraitExpressionTraitsFn --- src/TraitExpression.ts | 10 ++++++---- src/tests.ts | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index c0ea010..a20ca73 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -63,10 +63,12 @@ export class TraitExpression< export const emptyTraitExpression = new TraitExpression(TraitExpressionNullSuperclass, [] as const) interface PrependTraitSupertraitsFn extends Fn { - return: [ - ...Call, - this["arg0"], - ] + return: this["arg0"] extends Trait + ? [ + ...Call, + this["arg0"], + ] + : never } export interface TraitExpressionTraitsFn extends Fn { return: this["arg0"] extends TraitExpression diff --git a/src/tests.ts b/src/tests.ts index 710a660..421b746 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,5 @@ -import { Implements, abstract, expression, trait } from "." +import { Call } from "hotscript" +import { Implements, TraitExpressionTraitsFn, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( @@ -54,10 +55,11 @@ const builder = expression PrintsHelloOnNew, Identifiable(), // Identifiable(), + StatefulSubscription, ) const exp = builder.get() -type Abs = Implements +type Abs = Call class User extends exp.extends implements Implements { id: bigint = -1n -- 2.49.1 From f6d2d68eeee521caf0e1b79f115b308640f4e080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 03:19:33 +0100 Subject: [PATCH 43/65] Subtrait work --- src/TraitExpression.ts | 38 ++++++++++---------------------------- src/tests.ts | 22 +++++++++++++++++++--- src/trait.ts | 13 ++----------- 3 files changed, 31 insertions(+), 42 deletions(-) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index a20ca73..2d3f207 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,6 +1,6 @@ -import { Call, Fn, Pipe, Tuples } from "hotscript" +import { Call, ComposeLeft, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, Trait, TraitAbstractFn, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn } from "." +import { AbstractTag, Trait, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn } from "." import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" @@ -48,10 +48,10 @@ export class TraitExpression< SubtraitImplWithAbstract extends Class<{}>, >( abstract: ( - abstract: Pipe, - SimplifyFn, - ]> + abstract: Call< + ComposeLeft<[TraitExpressionAbstractFn, SimplifyFn]>, + typeof this + > ) => Opaque, // impl: () @@ -77,33 +77,15 @@ export interface TraitExpressionTraitsFn extends Fn { } export interface TraitExpressionAbstractFn extends Fn { - return: this["arg0"] extends TraitExpression - ? Pipe + ? Pipe, ExtendFn, ]> : never } -export interface TraitExpressionInstanceFn extends Fn { - return: this["arg0"] extends TraitExpression - ? Pipe - : never -} - -export interface TraitExpressionStaticFn extends Fn { - return: this["arg0"] extends TraitExpression - ? Pipe - : never -} - - export type Implements> = ( Exp extends TraitExpression ? Pipe +type Abs = Call, typeof exp> + +exp.subtrait( + s => { + interface Subtrait extends (typeof s) { + + } + + return abstract() + }, +) class User extends exp.extends implements Implements { + declare status: { _tag: "awaitingPayment" } | { _tag: "active"; activeSince: Date; expiresAt?: Date | undefined } | { _tag: "expired"; expiredSince: Date } id: bigint = -1n } diff --git a/src/trait.ts b/src/trait.ts index a028dc8..fda5316 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -1,7 +1,7 @@ import { Call, Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, TraitExpression, TraitExpressionAbstractFn, TraitExpressionNullSuperclass, TraitExpressionTraitsFn, emptyTraitExpression } from "." -import { ExtendFn, StaticMembers } from "./util" +import { AbstractTag, TraitExpression, TraitExpressionNullSuperclass, TraitExpressionTraitsFn, emptyTraitExpression } from "." +import { StaticMembers } from "./util" type AddAbstractToImplClass< @@ -83,15 +83,6 @@ export interface TraitSupertraitsFn extends Fn { : never } -export interface TraitAbstractFn extends Fn { - return: this["arg0"] extends Trait - ? Call, - Abstract, - ]> - : never -} - export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" -- 2.49.1 From 2d32e4807d99cf71abf2bd7c063bfaf7026020e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 03:32:12 +0100 Subject: [PATCH 44/65] Tests --- src/tests.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index 4ef5de9..2fd07a4 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,6 +1,5 @@ -import { Call, ComposeLeft, Pipe } from "hotscript" -import { Implements, TraitExpressionAbstractFn, TraitExpressionTraitsFn, abstract, expression, trait } from "." -import { Simplify } from "type-fest" +import { Call, ComposeLeft } from "hotscript" +import { Implements, TraitExpressionAbstractFn, abstract, expression, trait } from "." import { SimplifyFn } from "./util" @@ -66,15 +65,15 @@ type Abs = Call, typeof exp> -exp.subtrait( - s => { - interface Subtrait extends (typeof s) { +// exp.subtrait( +// s => { +// interface Subtrait extends (typeof s) { - } +// } - return abstract() - }, -) +// return abstract() +// }, +// ) class User extends exp.extends implements Implements { declare status: { _tag: "awaitingPayment" } | { _tag: "active"; activeSince: Date; expiresAt?: Date | undefined } | { _tag: "expired"; expiredSince: Date } -- 2.49.1 From bb5e85573cb48f30bee310dfa12eb85f3e26ecdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 04:26:20 +0100 Subject: [PATCH 45/65] TraitExpressionBuilder work --- src/TraitExpression.ts | 110 ++++------------------------ src/TraitExpressionBuilder.ts | 134 ++++++++++++++++++++++++++++++++++ src/index.ts | 1 + src/trait.ts | 2 +- 4 files changed, 149 insertions(+), 98 deletions(-) create mode 100644 src/TraitExpressionBuilder.ts diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 2d3f207..0e9cc13 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -7,19 +7,21 @@ import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpressionNullSuperclass {} export class TraitExpression< - Super extends AbstractClass<{}>, - Traits extends Trait[], + Super extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], > { constructor( readonly superclass: Super, - readonly traits: Traits, + readonly ownTraits: OwnTraits, + readonly allTraits: AllTraits, ) {} get extends(): ( AbstractClass< Pipe<[ InstanceType, - ...Call, Traits>, + ...Call, OwnTraits>, ], [ ExtendFn, SimplifyFn, @@ -30,14 +32,14 @@ export class TraitExpression< Pipe<[ Super, - ...Call, Traits>, + ...Call, OwnTraits>, ], [ Tuples.Map, ExtendFn, SimplifyFn, ]> ) { - return this.traits.reduce( + return this.ownTraits.reduce( (previous, trait) => trait.apply(previous), this.superclass as Opaque, ) as any @@ -60,7 +62,11 @@ export class TraitExpression< } } -export const emptyTraitExpression = new TraitExpression(TraitExpressionNullSuperclass, [] as const) +export const emptyTraitExpression = new TraitExpression( + TraitExpressionNullSuperclass, + [] as const, + [] as const, +) interface PrependTraitSupertraitsFn extends Fn { return: this["arg0"] extends Trait @@ -95,93 +101,3 @@ export type Implements> = ( ]> : never ) - - -class TraitExpressionBuilder< - Super extends AbstractClass<{}>, - Traits extends Trait[], -> { - constructor(public expression: TraitExpression) {} - - extends< - NewSuper extends AbstractClass - >(superclass: NewSuper) { - return new TraitExpressionBuilder( - new TraitExpression( - superclass, - this.expression.traits, - ) - ) - } - - expresses< - AppendTraits extends Trait[] - >(...traits: AppendTraits) { - return new TraitExpressionBuilder( - new TraitExpression( - this.expression.superclass, - [...this.expression.traits, ...traits] as const, - ) - ) - } - - get() { - return this.expression as GetTraitExpression - } - - then(fn: (expression: ReturnType) => V): V { - return fn(this.get()) - } -} - - -type AbstractMembersExtendable< - Super extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Call, - ...Call, Traits>, - ]> -) - -type ImplInstanceExtendable< - Super extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Call, - ...Call, Traits>, - ]> -) - -type ImplStaticMembersExtendable< - Super extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Pipe<[ - Super, - ...Call, Traits>, - ], [ - Tuples.Map, - ExtendableFn, - ]> -) - -type GetTraitExpression< - Super extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Call extends true - ? "Cannot express an empty list of traits." - : AbstractMembersExtendable extends false - ? "Type conflict between the traits abstract members and/or the superclass instance." - : ImplInstanceExtendable extends false - ? "Type conflict between the traits implementation instances and/or the superclass instance." - : ImplStaticMembersExtendable extends false - ? "Type conflict between the traits implementation static members and/or the superclass static members." - : TraitExpression -) - - -export const expression = new TraitExpressionBuilder(emptyTraitExpression) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts new file mode 100644 index 0000000..9de8c52 --- /dev/null +++ b/src/TraitExpressionBuilder.ts @@ -0,0 +1,134 @@ +import { Call, Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass } from "type-fest" +import { Trait, TraitExpression, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn, emptyTraitExpression } from "." +import { ExtendableFn, StaticMembersFn } from "./util" + + +class TraitExpressionBuilder< + Super extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], +> { + constructor(public expression: TraitExpression) {} + + extends< + NewSuper extends AbstractClass + >(superclass: NewSuper) { + return new TraitExpressionBuilder( + new TraitExpression( + superclass, + this.expression.ownTraits, + this.expression.allTraits, + ) + ) + } + + expresses< + Traits extends Trait[] + >( + ...traits: Traits + ) { + return new TraitExpressionBuilder( + new TraitExpression( + this.expression.superclass, + [...this.expression.ownTraits, ...traits] as const, + [ + ...this.expression.allTraits, + ...this.spreadSupertraits(traits) as SpreadTraitsHierarchy, + ] as const, + ) + ) + } + + private spreadSupertraits< + Traits extends Trait< + TraitExpression[]>, + any, + any + >[] + >( + traits: Traits + ) { + return traits.flatMap(trait => [ + ...trait.superExpression.allTraits, + trait, + ]) + } + + get() { + return this.expression as GetTraitExpression + } + + then(fn: (expression: ReturnType) => V): V { + return fn(this.get()) + } +} + + +type SpreadTraitsHierarchy[]> = ( + Call< + Tuples.FlatMap, + Traits + > +) +interface PrependTraitSupertraitsFn extends Fn { + return: this["arg0"] extends Trait + ? [ + ...Call, + this["arg0"], + ] + : never +} + + +type AbstractMembersExtendable< + Super extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplInstanceExtendable< + Super extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplStaticMembersExtendable< + Super extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Pipe<[ + Super, + ...Call, Traits>, + ], [ + Tuples.Map, + ExtendableFn, + ]> +) + +type GetTraitExpression< + Super extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], +> = ( + Call extends true + ? "Cannot express an empty list of traits." + : AbstractMembersExtendable extends false + ? "Type conflict between the traits abstract members and/or the superclass instance." + : ImplInstanceExtendable extends false + ? "Type conflict between the traits implementation instances and/or the superclass instance." + : ImplStaticMembersExtendable extends false + ? "Type conflict between the traits implementation static members and/or the superclass static members." + : TraitExpression +) + + +export const expression = new TraitExpressionBuilder(emptyTraitExpression) diff --git a/src/index.ts b/src/index.ts index b92ea0f..f9de698 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ export * from "./TraitExpression" +export * from "./TraitExpressionBuilder" export * from "./abstract" export * from "./trait" diff --git a/src/trait.ts b/src/trait.ts index fda5316..75d859e 100644 --- a/src/trait.ts +++ b/src/trait.ts @@ -28,7 +28,7 @@ type RemoveAbstractFromImplClass< export class Trait< - Super extends TraitExpression, + Super extends TraitExpression[], Trait[]>, Abstract extends {}, ImplClass extends Class<{}, []>, > { -- 2.49.1 From 74029493e8fddfb01d2db0590453de37917c1312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 17:33:05 +0100 Subject: [PATCH 46/65] trait -> Trait --- src/{trait.ts => Trait.ts} | 0 src/index.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{trait.ts => Trait.ts} (100%) diff --git a/src/trait.ts b/src/Trait.ts similarity index 100% rename from src/trait.ts rename to src/Trait.ts diff --git a/src/index.ts b/src/index.ts index f9de698..bf1c52b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ +export * from "./Trait" export * from "./TraitExpression" export * from "./TraitExpressionBuilder" export * from "./abstract" -export * from "./trait" -- 2.49.1 From 26daee364d95fdb34285e5e06da4d015e1d1b8ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 18:10:00 +0100 Subject: [PATCH 47/65] Trait refactoring --- src/Trait.ts | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 75d859e..cffd410 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -39,42 +39,52 @@ export class Trait< ) {} } -export interface TraitOwnAbstractFn extends Fn { - return: this["arg0"] extends Trait +export type TraitOwnAbstract = ( + T extends Trait ? Abstract : never +) +export interface TraitOwnAbstractFn extends Fn { + return: TraitOwnAbstract } -export type TraitOwnAbstract = Call -export interface TraitOwnImplClassFn extends Fn { - return: this["arg0"] extends Trait +export type TraitOwnImplClass = ( + T extends Trait ? ImplClass : never +) +export interface TraitOwnImplClassFn extends Fn { + return: TraitOwnImplClass } -export type TraitOwnImplClass = Call -export interface TraitOwnImplInstanceFn extends Fn { - return: this["arg0"] extends Trait +export type TraitOwnImplInstance = ( + T extends Trait ? InstanceType : never +) +export interface TraitOwnImplInstanceFn extends Fn { + return: TraitOwnImplInstance } -export type TraitOwnImplInstance = Call -export interface TraitOwnClassFn extends Fn { - return: this["arg0"] extends Trait +export type TraitOwnClass = ( + T extends Trait ? AddAbstractToImplClass : never +) +export interface TraitOwnClassFn extends Fn { + return: TraitOwnClass } -export type TraitOwnClass = Call -export interface TraitOwnInstanceFn extends Fn { - return: this["arg0"] extends Trait +export type TraitOwnInstance = ( + T extends Trait ? InstanceType< AddAbstractToImplClass > : never +) +export interface TraitOwnInstanceFn extends Fn { + return: TraitOwnInstance } -export type TraitOwnInstance = Call export interface TraitSupertraitsFn extends Fn { -- 2.49.1 From 1dd118d8560370b284c572196131ee3f2c8c69e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 22:01:16 +0100 Subject: [PATCH 48/65] Working TraitExpressionBuilder --- src/Trait.ts | 19 +++++---- src/TraitExpression.ts | 74 ++++++++++++++++++----------------- src/TraitExpressionBuilder.ts | 30 +++++++------- src/tests.ts | 9 +---- 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index cffd410..7422207 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -1,6 +1,6 @@ -import { Call, Fn } from "hotscript" +import { Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, TraitExpression, TraitExpressionNullSuperclass, TraitExpressionTraitsFn, emptyTraitExpression } from "." +import { AbstractTag, TraitExpression, TraitExpressionAllTraits, TraitExpressionNullSuperclass, emptyTraitExpression } from "." import { StaticMembers } from "./util" @@ -33,9 +33,9 @@ export class Trait< ImplClass extends Class<{}, []>, > { constructor( - readonly superExpression: Super, - readonly abstract: Abstract, - readonly apply: (Super: AbstractClass<{}>) => ImplClass, + readonly supertraits: Super, + readonly abstract: Abstract, + readonly apply: (Super: AbstractClass<{}>) => ImplClass, ) {} } @@ -87,10 +87,13 @@ export interface TraitOwnInstanceFn extends Fn { } -export interface TraitSupertraitsFn extends Fn { - return: this["arg0"] extends Trait - ? Call +export type TraitSupertraits = ( + T extends Trait + ? TraitExpressionAllTraits : never +) +export interface TraitSupertraitsFn extends Fn { + return: TraitSupertraits } diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 0e9cc13..1ea1b01 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,7 +1,7 @@ -import { Call, ComposeLeft, Fn, Pipe, Tuples } from "hotscript" +import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, Trait, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn } from "." -import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util" +import { AbstractTag, Trait, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn } from "." +import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpressionNullSuperclass {} @@ -39,7 +39,7 @@ export class TraitExpression< SimplifyFn, ]> ) { - return this.ownTraits.reduce( + return this.allTraits.reduce( (previous, trait) => trait.apply(previous), this.superclass as Opaque, ) as any @@ -50,10 +50,9 @@ export class TraitExpression< SubtraitImplWithAbstract extends Class<{}>, >( abstract: ( - abstract: Call< - ComposeLeft<[TraitExpressionAbstractFn, SimplifyFn]>, - typeof this - > + abstract: Pipe ) => Opaque, // impl: () @@ -62,42 +61,47 @@ export class TraitExpression< } } -export const emptyTraitExpression = new TraitExpression( - TraitExpressionNullSuperclass, - [] as const, - [] as const, +export type TraitExpressionSuper = ( + T extends TraitExpression + ? Super + : never ) - -interface PrependTraitSupertraitsFn extends Fn { - return: this["arg0"] extends Trait - ? [ - ...Call, - this["arg0"], - ] - : never -} -export interface TraitExpressionTraitsFn extends Fn { - return: this["arg0"] extends TraitExpression - ? Call, Traits> - : never +export interface TraitExpressionSuperFn extends Fn { + return: TraitExpressionSuper } -export interface TraitExpressionAbstractFn extends Fn { - return: this["arg0"] extends TraitExpression - ? Pipe, - ExtendFn, - ]> +export type TraitExpressionOwnTraits = ( + T extends TraitExpression + ? OwnTraits : never +) +export interface TraitExpressionOwnTraitsFn extends Fn { + return: TraitExpressionOwnTraits } -export type Implements> = ( - Exp extends TraitExpression - ? Pipe = ( + T extends TraitExpression + ? AllTraits + : never +) +export interface TraitExpressionAllTraitsFn extends Fn { + return: TraitExpressionAllTraits +} + + +export type Implements> = ( + Exp extends TraitExpression + ? Pipe, ExtendFn, SimplifyFn, ]> : never ) + + +export const emptyTraitExpression = new TraitExpression( + TraitExpressionNullSuperclass, + [] as const, + [] as const, +) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index 9de8c52..3974336 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -1,6 +1,6 @@ import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass } from "type-fest" -import { Trait, TraitExpression, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn, emptyTraitExpression } from "." +import { Trait, TraitExpression, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, emptyTraitExpression } from "." import { ExtendableFn, StaticMembersFn } from "./util" @@ -27,17 +27,18 @@ class TraitExpressionBuilder< Traits extends Trait[] >( ...traits: Traits - ) { + ): TraitExpressionBuilder< + Super, + [...OwnTraits, ...Traits], + [...AllTraits, SpreadSupertraits] + > { return new TraitExpressionBuilder( new TraitExpression( this.expression.superclass, [...this.expression.ownTraits, ...traits] as const, - [ - ...this.expression.allTraits, - ...this.spreadSupertraits(traits) as SpreadTraitsHierarchy, - ] as const, + [...this.expression.allTraits, ...this.spreadSupertraits(traits)] as const, ) - ) + ) as any } private spreadSupertraits< @@ -50,9 +51,9 @@ class TraitExpressionBuilder< traits: Traits ) { return traits.flatMap(trait => [ - ...trait.superExpression.allTraits, + ...trait.supertraits.allTraits, trait, - ]) + ]) as SpreadSupertraits } get() { @@ -65,18 +66,17 @@ class TraitExpressionBuilder< } -type SpreadTraitsHierarchy[]> = ( +type SpreadSupertraits[]> = ( Call< Tuples.FlatMap, Traits > ) interface PrependTraitSupertraitsFn extends Fn { - return: this["arg0"] extends Trait - ? [ - ...Call, - this["arg0"], - ] + return: this["arg0"] extends Trait + ? Super extends TraitExpression + ? [...AllTraits, this["arg0"]] + : never : never } diff --git a/src/tests.ts b/src/tests.ts index 2fd07a4..6a03f21 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,6 +1,4 @@ -import { Call, ComposeLeft } from "hotscript" -import { Implements, TraitExpressionAbstractFn, abstract, expression, trait } from "." -import { SimplifyFn } from "./util" +import { Implements, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( @@ -60,10 +58,7 @@ const builder = expression ) const exp = builder.get() -type Abs = Call, typeof exp> +type Abs = Implements // exp.subtrait( // s => { -- 2.49.1 From 891db74032ac45e64301059e655c81f9170cf5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 22:20:19 +0100 Subject: [PATCH 49/65] Moved Trait helper types to a namespace --- src/Trait.ts | 101 +++++++++++++++++----------------- src/TraitExpressionBuilder.ts | 8 +-- src/tests.ts | 2 +- 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 7422207..95719cd 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -39,61 +39,62 @@ export class Trait< ) {} } -export type TraitOwnAbstract = ( - T extends Trait - ? Abstract - : never -) -export interface TraitOwnAbstractFn extends Fn { - return: TraitOwnAbstract -} +export namespace Trait { + export type OwnAbstract = ( + T extends Trait + ? Abstract + : never + ) + export interface OwnAbstractFn extends Fn { + return: Trait.OwnAbstract + } -export type TraitOwnImplClass = ( - T extends Trait - ? ImplClass - : never -) -export interface TraitOwnImplClassFn extends Fn { - return: TraitOwnImplClass -} + export type OwnImplClass = ( + T extends Trait + ? ImplClass + : never + ) + export interface OwnImplClassFn extends Fn { + return: Trait.OwnImplClass + } -export type TraitOwnImplInstance = ( - T extends Trait - ? InstanceType - : never -) -export interface TraitOwnImplInstanceFn extends Fn { - return: TraitOwnImplInstance -} + export type OwnImplInstance = ( + T extends Trait + ? InstanceType + : never + ) + export interface OwnImplInstanceFn extends Fn { + return: Trait.OwnImplInstance + } -export type TraitOwnClass = ( - T extends Trait - ? AddAbstractToImplClass - : never -) -export interface TraitOwnClassFn extends Fn { - return: TraitOwnClass -} + export type OwnClass = ( + T extends Trait + ? AddAbstractToImplClass + : never + ) + export interface OwnClassFn extends Fn { + return: Trait.OwnClass + } -export type TraitOwnInstance = ( - T extends Trait - ? InstanceType< - AddAbstractToImplClass - > - : never -) -export interface TraitOwnInstanceFn extends Fn { - return: TraitOwnInstance -} + export type OwnInstance = ( + T extends Trait + ? InstanceType< + AddAbstractToImplClass + > + : never + ) + export interface OwnInstanceFn extends Fn { + return: Trait.OwnInstance + } - -export type TraitSupertraits = ( - T extends Trait - ? TraitExpressionAllTraits - : never -) -export interface TraitSupertraitsFn extends Fn { - return: TraitSupertraits + export type Supertraits = ( + T extends Trait + ? TraitExpressionAllTraits + : never + ) + export interface SupertraitsFn extends Fn { + return: Trait.Supertraits + } } diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index 3974336..bd926d3 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -1,6 +1,6 @@ import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass } from "type-fest" -import { Trait, TraitExpression, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, emptyTraitExpression } from "." +import { Trait, TraitExpression, emptyTraitExpression } from "." import { ExtendableFn, StaticMembersFn } from "./util" @@ -87,7 +87,7 @@ type AbstractMembersExtendable< > = ( Call, - ...Call, Traits>, + ...Call, Traits>, ]> ) @@ -97,7 +97,7 @@ type ImplInstanceExtendable< > = ( Call, - ...Call, Traits>, + ...Call, Traits>, ]> ) @@ -107,7 +107,7 @@ type ImplStaticMembersExtendable< > = ( Pipe<[ Super, - ...Call, Traits>, + ...Call, Traits>, ], [ Tuples.Map, ExtendableFn, diff --git a/src/tests.ts b/src/tests.ts index 6a03f21..e225d7f 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, abstract, expression, trait } from "." +import { Implements, Trait, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( -- 2.49.1 From 8d2cb90f5237a2178fddc72fd89baa4b3140fe75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 22:20:50 +0100 Subject: [PATCH 50/65] Moved Trait helper types to a namespace --- src/TraitExpression.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 1ea1b01..883075a 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,6 +1,6 @@ import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, Trait, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn } from "." +import { AbstractTag, Trait, TraitApplierSuperTag } from "." import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" @@ -21,7 +21,7 @@ export class TraitExpression< AbstractClass< Pipe<[ InstanceType, - ...Call, OwnTraits>, + ...Call, OwnTraits>, ], [ ExtendFn, SimplifyFn, @@ -32,7 +32,7 @@ export class TraitExpression< Pipe<[ Super, - ...Call, OwnTraits>, + ...Call, OwnTraits>, ], [ Tuples.Map, ExtendFn, @@ -92,7 +92,7 @@ export interface TraitExpressionAllTraitsFn extends Fn { export type Implements> = ( Exp extends TraitExpression ? Pipe, + Tuples.Map, ExtendFn, SimplifyFn, ]> -- 2.49.1 From f6f56b74cd9a83d19c1381287109b15ddcf956fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 22:50:13 +0100 Subject: [PATCH 51/65] Moved TraitExpression helpers to namespace --- src/Trait.ts | 4 +-- src/TraitExpression.ts | 48 ++++++++++++++++++----------------- src/TraitExpressionBuilder.ts | 8 +++--- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 95719cd..24cd8f4 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -1,6 +1,6 @@ import { Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, TraitExpression, TraitExpressionAllTraits, TraitExpressionNullSuperclass, emptyTraitExpression } from "." +import { AbstractTag, TraitExpression, TraitExpressionNullSuperclass, emptyTraitExpression } from "." import { StaticMembers } from "./util" @@ -89,7 +89,7 @@ export namespace Trait { export type Supertraits = ( T extends Trait - ? TraitExpressionAllTraits + ? TraitExpression.AllTraits : never ) export interface SupertraitsFn extends Fn { diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 883075a..1296550 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -61,31 +61,33 @@ export class TraitExpression< } } -export type TraitExpressionSuper = ( - T extends TraitExpression - ? Super - : never -) -export interface TraitExpressionSuperFn extends Fn { - return: TraitExpressionSuper -} +export namespace TraitExpression { + export type Super = ( + T extends TraitExpression + ? Super + : never + ) + export interface SuperFn extends Fn { + return: TraitExpression.Super + } -export type TraitExpressionOwnTraits = ( - T extends TraitExpression - ? OwnTraits - : never -) -export interface TraitExpressionOwnTraitsFn extends Fn { - return: TraitExpressionOwnTraits -} + export type OwnTraits = ( + T extends TraitExpression + ? OwnTraits + : never + ) + export interface OwnTraitsFn extends Fn { + return: TraitExpression.OwnTraits + } -export type TraitExpressionAllTraits = ( - T extends TraitExpression - ? AllTraits - : never -) -export interface TraitExpressionAllTraitsFn extends Fn { - return: TraitExpressionAllTraits + export type AllTraits = ( + T extends TraitExpression + ? AllTraits + : never + ) + export interface AllTraitsFn extends Fn { + return: TraitExpression.AllTraits + } } diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index bd926d3..0af24ff 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -119,13 +119,13 @@ type GetTraitExpression< OwnTraits extends Trait[], AllTraits extends Trait[], > = ( - Call extends true + Call extends true ? "Cannot express an empty list of traits." - : AbstractMembersExtendable extends false + : AbstractMembersExtendable extends false ? "Type conflict between the traits abstract members and/or the superclass instance." - : ImplInstanceExtendable extends false + : ImplInstanceExtendable extends false ? "Type conflict between the traits implementation instances and/or the superclass instance." - : ImplStaticMembersExtendable extends false + : ImplStaticMembersExtendable extends false ? "Type conflict between the traits implementation static members and/or the superclass static members." : TraitExpression ) -- 2.49.1 From 56e4af73023b9dcdf243948c66f0645144a195e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 22:58:42 +0100 Subject: [PATCH 52/65] Super -> Superclass --- src/TraitExpression.ts | 26 +++++++++++++------------- src/tests.ts | 4 +++- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 1296550..e24cb6d 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -7,12 +7,12 @@ import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpressionNullSuperclass {} export class TraitExpression< - Super extends AbstractClass<{}>, - OwnTraits extends Trait[], - AllTraits extends Trait[], + Superclass extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], > { constructor( - readonly superclass: Super, + readonly superclass: Superclass, readonly ownTraits: OwnTraits, readonly allTraits: AllTraits, ) {} @@ -20,18 +20,18 @@ export class TraitExpression< get extends(): ( AbstractClass< Pipe<[ - InstanceType, + InstanceType, ...Call, OwnTraits>, ], [ ExtendFn, SimplifyFn, ]>, - ConstructorParameters + ConstructorParameters > & Pipe<[ - Super, + Superclass, ...Call, OwnTraits>, ], [ Tuples.Map, @@ -41,7 +41,7 @@ export class TraitExpression< ) { return this.allTraits.reduce( (previous, trait) => trait.apply(previous), - this.superclass as Opaque, + this.superclass as Opaque, ) as any } @@ -62,13 +62,13 @@ export class TraitExpression< } export namespace TraitExpression { - export type Super = ( - T extends TraitExpression - ? Super + export type Superclass = ( + T extends TraitExpression + ? Superclass : never ) - export interface SuperFn extends Fn { - return: TraitExpression.Super + export interface SuperclassFn extends Fn { + return: TraitExpression.Superclass } export type OwnTraits = ( diff --git a/src/tests.ts b/src/tests.ts index e225d7f..1bc7e75 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, Trait, abstract, expression, trait } from "." +import { Implements, Trait, TraitExpression, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( @@ -57,6 +57,8 @@ const builder = expression StatefulSubscription, ) +type T = TraitExpression.OwnTraits + const exp = builder.get() type Abs = Implements -- 2.49.1 From 33275ae63eacb9156c6cb13f0cd80b24dc94e4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 4 Feb 2024 23:59:12 +0100 Subject: [PATCH 53/65] Work --- src/Trait.ts | 21 +++++++++++++------ src/TraitExpressionBuilder.ts | 38 ++++++++++++++++------------------- src/tests.ts | 2 +- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 24cd8f4..3637455 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -28,18 +28,27 @@ type RemoveAbstractFromImplClass< export class Trait< - Super extends TraitExpression[], Trait[]>, - Abstract extends {}, - ImplClass extends Class<{}, []>, + Supertraits extends TraitExpression[], Trait[]>, + Abstract extends {}, + ImplClass extends Class<{}, []>, > { constructor( - readonly supertraits: Super, + readonly supertraits: Supertraits, readonly abstract: Abstract, readonly apply: (Super: AbstractClass<{}>) => ImplClass, ) {} } export namespace Trait { + export type OwnSupertraits = ( + T extends Trait + ? Supertraits + : never + ) + export interface OwnSupertraitsFn extends Fn { + return: Trait.OwnSupertraits + } + export type OwnAbstract = ( T extends Trait ? Abstract @@ -88,8 +97,8 @@ export namespace Trait { } export type Supertraits = ( - T extends Trait - ? TraitExpression.AllTraits + T extends Trait + ? TraitExpression.AllTraits : never ) export interface SupertraitsFn extends Fn { diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index 0af24ff..a6c39a5 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -73,40 +73,36 @@ type SpreadSupertraits[]> = ( > ) interface PrependTraitSupertraitsFn extends Fn { - return: this["arg0"] extends Trait - ? Super extends TraitExpression - ? [...AllTraits, this["arg0"]] - : never - : never + return: [...Trait.Supertraits, this["arg0"]] } type AbstractMembersExtendable< - Super extends AbstractClass<{}>, - Traits extends Trait[], + Superclass extends AbstractClass<{}>, + Traits extends Trait[], > = ( Call, + InstanceType, ...Call, Traits>, ]> ) type ImplInstanceExtendable< - Super extends AbstractClass<{}>, - Traits extends Trait[], + Superclass extends AbstractClass<{}>, + Traits extends Trait[], > = ( Call, + InstanceType, ...Call, Traits>, ]> ) type ImplStaticMembersExtendable< - Super extends AbstractClass<{}>, - Traits extends Trait[], + Superclass extends AbstractClass<{}>, + Traits extends Trait[], > = ( Pipe<[ - Super, + Superclass, ...Call, Traits>, ], [ Tuples.Map, @@ -115,19 +111,19 @@ type ImplStaticMembersExtendable< ) type GetTraitExpression< - Super extends AbstractClass<{}>, - OwnTraits extends Trait[], - AllTraits extends Trait[], + Superclass extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], > = ( Call extends true ? "Cannot express an empty list of traits." - : AbstractMembersExtendable extends false + : AbstractMembersExtendable extends false ? "Type conflict between the traits abstract members and/or the superclass instance." - : ImplInstanceExtendable extends false + : ImplInstanceExtendable extends false ? "Type conflict between the traits implementation instances and/or the superclass instance." - : ImplStaticMembersExtendable extends false + : ImplStaticMembersExtendable extends false ? "Type conflict between the traits implementation static members and/or the superclass static members." - : TraitExpression + : TraitExpression ) diff --git a/src/tests.ts b/src/tests.ts index 1bc7e75..c0a35ca 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -57,7 +57,7 @@ const builder = expression StatefulSubscription, ) -type T = TraitExpression.OwnTraits +type T = TraitExpression.AllTraits const exp = builder.get() type Abs = Implements -- 2.49.1 From 463c8f1586e96e751ae8ed27a65520d43b2c294e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 5 Feb 2024 00:07:07 +0100 Subject: [PATCH 54/65] Refactoring --- src/Trait.ts | 4 ++-- src/TraitExpression.ts | 6 +++--- src/tests.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 3637455..b3fdb42 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -1,6 +1,6 @@ import { Fn } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, TraitExpression, TraitExpressionNullSuperclass, emptyTraitExpression } from "." +import { AbstractTag, TraitExpression, emptyTraitExpression } from "." import { StaticMembers } from "./util" @@ -28,7 +28,7 @@ type RemoveAbstractFromImplClass< export class Trait< - Supertraits extends TraitExpression[], Trait[]>, + Supertraits extends TraitExpression[], Trait[]>, Abstract extends {}, ImplClass extends Class<{}, []>, > { diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index e24cb6d..c51a32a 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -4,8 +4,6 @@ import { AbstractTag, Trait, TraitApplierSuperTag } from "." import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" -export class TraitExpressionNullSuperclass {} - export class TraitExpression< Superclass extends AbstractClass<{}>, OwnTraits extends Trait[], @@ -62,6 +60,8 @@ export class TraitExpression< } export namespace TraitExpression { + export class NullSuperclass {} + export type Superclass = ( T extends TraitExpression ? Superclass @@ -103,7 +103,7 @@ export type Implements> = ( export const emptyTraitExpression = new TraitExpression( - TraitExpressionNullSuperclass, + TraitExpression.NullSuperclass, [] as const, [] as const, ) diff --git a/src/tests.ts b/src/tests.ts index c0a35ca..4aef87e 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, Trait, TraitExpression, abstract, expression, trait } from "." +import { Implements, TraitExpression, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( -- 2.49.1 From 7b73cfbf92f78c65a9c1d7243bef65c093432d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 5 Feb 2024 00:43:41 +0100 Subject: [PATCH 55/65] Fixed! --- src/TraitExpressionBuilder.ts | 4 ++-- src/tests.ts | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index a6c39a5..47fd088 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -9,7 +9,7 @@ class TraitExpressionBuilder< OwnTraits extends Trait[], AllTraits extends Trait[], > { - constructor(public expression: TraitExpression) {} + constructor(private expression: TraitExpression) {} extends< NewSuper extends AbstractClass @@ -30,7 +30,7 @@ class TraitExpressionBuilder< ): TraitExpressionBuilder< Super, [...OwnTraits, ...Traits], - [...AllTraits, SpreadSupertraits] + [...AllTraits, ...SpreadSupertraits] > { return new TraitExpressionBuilder( new TraitExpression( diff --git a/src/tests.ts b/src/tests.ts index 4aef87e..6a03f21 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, TraitExpression, abstract, expression, trait } from "." +import { Implements, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( @@ -57,8 +57,6 @@ const builder = expression StatefulSubscription, ) -type T = TraitExpression.AllTraits - const exp = builder.get() type Abs = Implements -- 2.49.1 From 99662ecc311a8e404599363de820288ec27175f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 5 Feb 2024 00:48:09 +0100 Subject: [PATCH 56/65] Fix --- src/TraitExpression.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index c51a32a..2599a3d 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -19,7 +19,7 @@ export class TraitExpression< AbstractClass< Pipe<[ InstanceType, - ...Call, OwnTraits>, + ...Call, AllTraits>, ], [ ExtendFn, SimplifyFn, @@ -30,7 +30,7 @@ export class TraitExpression< Pipe<[ Superclass, - ...Call, OwnTraits>, + ...Call, AllTraits>, ], [ Tuples.Map, ExtendFn, -- 2.49.1 From a123da55fe97d823853a2fac8a3e8a27cd376766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 5 Feb 2024 01:04:19 +0100 Subject: [PATCH 57/65] get() -> build() --- src/TraitExpressionBuilder.ts | 16 +++++++++------- src/tests.ts | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index 47fd088..5aa95e0 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -12,8 +12,10 @@ class TraitExpressionBuilder< constructor(private expression: TraitExpression) {} extends< - NewSuper extends AbstractClass - >(superclass: NewSuper) { + Super extends AbstractClass + >( + superclass: Super + ) { return new TraitExpressionBuilder( new TraitExpression( superclass, @@ -56,12 +58,12 @@ class TraitExpressionBuilder< ]) as SpreadSupertraits } - get() { - return this.expression as GetTraitExpression + build() { + return this.expression as BuildTraitExpression } - then(fn: (expression: ReturnType) => V): V { - return fn(this.get()) + then(fn: (expression: ReturnType) => V): V { + return fn(this.build()) } } @@ -110,7 +112,7 @@ type ImplStaticMembersExtendable< ]> ) -type GetTraitExpression< +type BuildTraitExpression< Superclass extends AbstractClass<{}>, OwnTraits extends Trait[], AllTraits extends Trait[], diff --git a/src/tests.ts b/src/tests.ts index 6a03f21..c80b6a2 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -48,7 +48,7 @@ class TestSuperclass { } -const builder = expression +const exp = expression .extends(TestSuperclass) .expresses( PrintsHelloOnNew, @@ -56,8 +56,8 @@ const builder = expression // Identifiable(), StatefulSubscription, ) + .build() -const exp = builder.get() type Abs = Implements // exp.subtrait( -- 2.49.1 From 6853bcbee8e6a133fc79eaacc41e95fd11a5c1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 5 Feb 2024 03:19:12 +0100 Subject: [PATCH 58/65] Working subtraiting --- src/Trait.ts | 4 +- src/TraitExpression.ts | 43 ++++++------ src/TraitExpressionBuilder.ts | 123 +++++++++++++++++----------------- src/tests.ts | 28 +++++--- src/util/extend.ts | 7 +- src/util/inheritance.ts | 8 +-- src/util/misc.ts | 11 +++ 7 files changed, 121 insertions(+), 103 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index b3fdb42..5127d69 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -4,7 +4,7 @@ import { AbstractTag, TraitExpression, emptyTraitExpression } from "." import { StaticMembers } from "./util" -type AddAbstractToImplClass< +export type AddAbstractToImplClass< ImplClass extends Class<{}, []>, Abstract extends {}, > = ( @@ -15,7 +15,7 @@ type AddAbstractToImplClass< StaticMembers ) -type RemoveAbstractFromImplClass< +export type RemoveAbstractFromImplClass< ImplClassWithAbstract extends Class, Abstract extends {}, > = ( diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 2599a3d..4c66717 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,7 +1,7 @@ import { Call, Fn, Pipe, Tuples } from "hotscript" -import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, Trait, TraitApplierSuperTag } from "." -import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" +import { AbstractClass, Class, Opaque, Simplify } from "type-fest" +import { AbstractTag, RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "." +import { CommonKeys, ExtendFn, KeysOnlyInLeft, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpression< @@ -44,18 +44,22 @@ export class TraitExpression< } subtrait< - SubtraitAbstract extends {}, - SubtraitImplWithAbstract extends Class<{}>, + SubtraitAbstract extends Implements, + SubtraitImplClassWithAbstract extends Class, >( - abstract: ( - abstract: Pipe - ) => Opaque, - - // impl: () + abstract: (expression: typeof this) => Opaque, + apply: (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ), ) { - + return new Trait( + this, + {} as Simplify< + CommonKeys> & + KeysOnlyInLeft> + >, + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + ) } } @@ -90,6 +94,12 @@ export namespace TraitExpression { } } +export const emptyTraitExpression = new TraitExpression( + TraitExpression.NullSuperclass, + [] as const, + [] as const, +) + export type Implements> = ( Exp extends TraitExpression @@ -100,10 +110,3 @@ export type Implements> = ( ]> : never ) - - -export const emptyTraitExpression = new TraitExpression( - TraitExpression.NullSuperclass, - [] as const, - [] as const, -) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index 5aa95e0..a4b5b67 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -4,6 +4,67 @@ import { Trait, TraitExpression, emptyTraitExpression } from "." import { ExtendableFn, StaticMembersFn } from "./util" +type SpreadSupertraits[]> = ( + Call< + Tuples.FlatMap, + Traits + > +) +interface PrependTraitSupertraitsFn extends Fn { + return: [...Trait.Supertraits, this["arg0"]] +} + + +type AbstractMembersExtendable< + Superclass extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplInstanceExtendable< + Superclass extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplStaticMembersExtendable< + Superclass extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Pipe<[ + Superclass, + ...Call, Traits>, + ], [ + Tuples.Map, + ExtendableFn, + ]> +) + +type BuildTraitExpression< + Superclass extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], +> = ( + Call extends true + ? "Cannot express an empty list of traits." + : AbstractMembersExtendable extends false + ? "Type conflict between the traits abstract members and/or the superclass instance." + : ImplInstanceExtendable extends false + ? "Type conflict between the traits implementation instances and/or the superclass instance." + : ImplStaticMembersExtendable extends false + ? "Type conflict between the traits implementation static members and/or the superclass static members." + : TraitExpression +) + + class TraitExpressionBuilder< Super extends AbstractClass<{}>, OwnTraits extends Trait[], @@ -67,66 +128,4 @@ class TraitExpressionBuilder< } } - -type SpreadSupertraits[]> = ( - Call< - Tuples.FlatMap, - Traits - > -) -interface PrependTraitSupertraitsFn extends Fn { - return: [...Trait.Supertraits, this["arg0"]] -} - - -type AbstractMembersExtendable< - Superclass extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Call, - ...Call, Traits>, - ]> -) - -type ImplInstanceExtendable< - Superclass extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Call, - ...Call, Traits>, - ]> -) - -type ImplStaticMembersExtendable< - Superclass extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Pipe<[ - Superclass, - ...Call, Traits>, - ], [ - Tuples.Map, - ExtendableFn, - ]> -) - -type BuildTraitExpression< - Superclass extends AbstractClass<{}>, - OwnTraits extends Trait[], - AllTraits extends Trait[], -> = ( - Call extends true - ? "Cannot express an empty list of traits." - : AbstractMembersExtendable extends false - ? "Type conflict between the traits abstract members and/or the superclass instance." - : ImplInstanceExtendable extends false - ? "Type conflict between the traits implementation instances and/or the superclass instance." - : ImplStaticMembersExtendable extends false - ? "Type conflict between the traits implementation static members and/or the superclass static members." - : TraitExpression -) - - export const expression = new TraitExpressionBuilder(emptyTraitExpression) diff --git a/src/tests.ts b/src/tests.ts index c80b6a2..e80c955 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,4 @@ -import { Implements, abstract, expression, trait } from "." +import { Implements, Trait, abstract, expression, trait } from "." const PrintsHelloOnNew = trait( @@ -22,6 +22,7 @@ const Identifiable = () => trait( const StatefulSubscription = trait( abstract<{ + readonly isStatefulSubscription: true readonly status: ( { _tag: "awaitingPayment" } | { _tag: "active", activeSince: Date, expiresAt?: Date } | @@ -32,14 +33,23 @@ const StatefulSubscription = trait( Super => class StatefulSubscription extends Super {}, ) -// interface ActiveStatefulSubscriptionAbstractMembers extends TraitAbstractMembers { -// readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } -// } +const ActiveStatefulSubscription = expression + .expresses(StatefulSubscription) + .build() + .subtrait( + exp => { + interface IActiveStatefulSubscription extends Implements { + readonly isActiveStatefulSubscription: true + readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } + } -// const ActiveStatefulSubscription = trait( -// abstract(), -// Super => class ActiveStatefulSubscription extends Super {}, -// ) + return abstract() + }, + + Super => class ActiveStatefulSubscription extends Super {}, + ) + +type T = Trait.OwnAbstract class TestSuperclass { @@ -47,7 +57,6 @@ class TestSuperclass { // static test = 69 } - const exp = expression .extends(TestSuperclass) .expresses( @@ -71,6 +80,7 @@ type Abs = Implements // ) class User extends exp.extends implements Implements { + readonly isStatefulSubscription: true = true declare status: { _tag: "awaitingPayment" } | { _tag: "active"; activeSince: Date; expiresAt?: Date | undefined } | { _tag: "expired"; expiredSince: Date } id: bigint = -1n } diff --git a/src/util/extend.ts b/src/util/extend.ts index a7ee625..d675de5 100644 --- a/src/util/extend.ts +++ b/src/util/extend.ts @@ -1,8 +1,7 @@ import { Call, ComposeLeft, Fn, Match, Tuples } from "hotscript" +import { CommonKeys } from "." -type CommonKeys = Extract - type ExtendReducer = ( Pick> extends Pick> ? Omit> & Self @@ -13,7 +12,7 @@ interface ExtendReducerFn extends Fn { } export type ExtendFn = Tuples.Reduce -export type Extend = Call +export type Extend = Call export type ExtendableFn = ComposeLeft<[ @@ -23,4 +22,4 @@ export type ExtendableFn = ComposeLeft<[ Match.With, ]> ]> -export type Extendable = Call +export type Extendable = Call diff --git a/src/util/inheritance.ts b/src/util/inheritance.ts index a179d78..8d9a516 100644 --- a/src/util/inheritance.ts +++ b/src/util/inheritance.ts @@ -1,9 +1,5 @@ -/** - * Represents the common keys between two types. - * @template A - The first type. - * @template B - The second type. - */ -export type CommonKeys = Extract +import { CommonKeys } from "." + /** * Merges an inheritance tree defined by an array of types, considering overrides. diff --git a/src/util/misc.ts b/src/util/misc.ts index d67c57e..eee119a 100644 --- a/src/util/misc.ts +++ b/src/util/misc.ts @@ -2,6 +2,17 @@ import { Fn } from "hotscript" import { Simplify } from "type-fest" +/** + * Represents the common keys between two types. + * @template A - The first type. + * @template B - The second type. + */ +export type CommonKeys = Extract + +export type KeysOnlyInLeft = { + [K in Exclude]: Left[K] +} + export interface SimplifyFn extends Fn { return: Simplify } -- 2.49.1 From 793d288d8b2c62133a93cc54fc8a7bba7f9ebf9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 5 Feb 2024 04:01:02 +0100 Subject: [PATCH 59/65] Working compilation --- rollup.config.ts | 2 +- src/TraitExpression.ts | 16 ++++++++++------ src/lib.ts | 5 +++++ 3 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 src/lib.ts diff --git a/rollup.config.ts b/rollup.config.ts index bca2cda..22d5101 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -6,7 +6,7 @@ import pkg from "./package.json" assert { type: "json" } export default defineConfig({ - input: "src/index.ts", + input: "src/lib.ts", output: [ { diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 4c66717..6f02ec7 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,7 +1,14 @@ import { Call, Fn, Pipe, Tuples } from "hotscript" -import { AbstractClass, Class, Opaque, Simplify } from "type-fest" +import { AbstractClass, Class, Opaque } from "type-fest" import { AbstractTag, RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "." -import { CommonKeys, ExtendFn, KeysOnlyInLeft, SimplifyFn, StaticMembersFn } from "./util" +import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" + + +type RemoveSupertraitsAbstractFromAbstract = { + [Key in Extract]: Left[Key] +} & { + [Key in Exclude]: Left[Key] +} export class TraitExpression< @@ -54,10 +61,7 @@ export class TraitExpression< ) { return new Trait( this, - {} as Simplify< - CommonKeys> & - KeysOnlyInLeft> - >, + {} as RemoveSupertraitsAbstractFromAbstract>, apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, ) } diff --git a/src/lib.ts b/src/lib.ts new file mode 100644 index 0000000..c929b01 --- /dev/null +++ b/src/lib.ts @@ -0,0 +1,5 @@ +export { + abstract, expression, trait, + type Trait, + type TraitExpression +} from "." -- 2.49.1 From bf711706678aaad8864c67a047c7cdc157862839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 5 Feb 2024 04:59:49 +0100 Subject: [PATCH 60/65] Dependencies upgrade --- bun.lockb | Bin 155678 -> 155678 bytes package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/bun.lockb b/bun.lockb index c3c0b09247cff1be9abe12a541d885a7f62b184f..1aa0c800bb2453190ab6462bf94fee3e72b2f76d 100755 GIT binary patch delta 151 zcmV;I0BHZ7zzLqf36L%zJt?Hkf2w|FLqgBE&j^Z)1VV2eR;_q@9!O3nWEo4vu};3-gPskiL(JQYgQ144MKVg*aZmA6kgS zD8KH3w;eE*(_Fr8Fjwcc{Tp>b(C{d6TOWgMnYV430hbN|GPeb&0rEVTQ%eFMw-@CB F2YVJXKm7mz delta 147 zcmV;E0BrxBzzLqf36L%zbdJWl0qwQQ3jCc*%!`18>$NF?=f^0U_^@pvL@OHLu}K;vuGN{en9P+$zeKrxy?Aagh)wiVqb95C?DU%)DzGiXw>B%3aF5a0e&Peeyo_8 zAUe;i(2FkQ>d6VA;a5 Date: Mon, 5 Feb 2024 22:49:37 +0100 Subject: [PATCH 61/65] Work --- src/Trait.ts | 2 +- src/TraitExpression.ts | 13 +++++++------ src/tests.ts | 15 +++------------ src/util/class.ts | 15 --------------- src/util/index.ts | 1 - src/util/misc.ts | 17 ++++++++++++----- 6 files changed, 23 insertions(+), 40 deletions(-) delete mode 100644 src/util/class.ts diff --git a/src/Trait.ts b/src/Trait.ts index 5127d69..8e0d198 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -9,7 +9,7 @@ export type AddAbstractToImplClass< Abstract extends {}, > = ( Class< - InstanceType & Abstract, + Abstract & InstanceType, ConstructorParameters > & StaticMembers diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 6f02ec7..9bbdbb2 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -4,11 +4,11 @@ import { AbstractTag, RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" -type RemoveSupertraitsAbstractFromAbstract = { - [Key in Extract]: Left[Key] -} & { - [Key in Exclude]: Left[Key] -} +// type RemoveSupertraitsAbstractFromAbstract = { +// [Key in Extract]: Left[Key] +// } & { +// [Key in Exclude]: Left[Key] +// } export class TraitExpression< @@ -61,7 +61,8 @@ export class TraitExpression< ) { return new Trait( this, - {} as RemoveSupertraitsAbstractFromAbstract>, + // {} as RemoveSupertraitsAbstractFromAbstract>, + {} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements from this. apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, ) } diff --git a/src/tests.ts b/src/tests.ts index e80c955..c285337 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -63,25 +63,16 @@ const exp = expression PrintsHelloOnNew, Identifiable(), // Identifiable(), - StatefulSubscription, + ActiveStatefulSubscription, ) .build() type Abs = Implements -// exp.subtrait( -// s => { -// interface Subtrait extends (typeof s) { - -// } - -// return abstract() -// }, -// ) - class User extends exp.extends implements Implements { readonly isStatefulSubscription: true = true - declare status: { _tag: "awaitingPayment" } | { _tag: "active"; activeSince: Date; expiresAt?: Date | undefined } | { _tag: "expired"; expiredSince: Date } + readonly isActiveStatefulSubscription: true = true + declare status: { _tag: "active"; activeSince: Date; expiresAt?: Date | undefined } id: bigint = -1n } diff --git a/src/util/class.ts b/src/util/class.ts deleted file mode 100644 index 45215e0..0000000 --- a/src/util/class.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Fn } from "hotscript" -import { AbstractClass } from "type-fest" - - -/** - * Represents the static members of a class. - * @template Class - A class extending AbstractClass. - */ -export type StaticMembers> = ( - Omit -) - -export interface StaticMembersFn extends Fn { - return: StaticMembers -} diff --git a/src/util/index.ts b/src/util/index.ts index c0b49af..720a972 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1,4 +1,3 @@ -export * from "./class" export * from "./extend" export * from "./inheritance" export * from "./misc" diff --git a/src/util/misc.ts b/src/util/misc.ts index eee119a..3e19396 100644 --- a/src/util/misc.ts +++ b/src/util/misc.ts @@ -1,5 +1,5 @@ import { Fn } from "hotscript" -import { Simplify } from "type-fest" +import { AbstractClass, Simplify } from "type-fest" /** @@ -9,10 +9,17 @@ import { Simplify } from "type-fest" */ export type CommonKeys = Extract -export type KeysOnlyInLeft = { - [K in Exclude]: Left[K] -} - export interface SimplifyFn extends Fn { return: Simplify } + +/** + * Represents the static members of a class. + * @template Class - A class extending AbstractClass. + */ +export type StaticMembers> = ( + Omit +) +export interface StaticMembersFn extends Fn { + return: StaticMembers +} -- 2.49.1 From 23a6c6cfe4e3fe7b63909fbd454aa8588d92bf65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 6 Feb 2024 00:04:40 +0100 Subject: [PATCH 62/65] Lib exports --- package.json | 10 +++++++++ rollup.config.ts | 54 ++++++++++++++++++++++++++++-------------------- src/lib.ts | 1 + src/util/lib.ts | 6 ++++++ 4 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 src/util/lib.ts diff --git a/package.json b/package.json index 50a6587..8402d8d 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,16 @@ "types": "./dist/lib.d.cts", "default": "./dist/lib.cjs" } + }, + "./util": { + "import": { + "types": "./dist/util.d.mts", + "default": "./dist/util.mjs" + }, + "require": { + "types": "./dist/util.d.cts", + "default": "./dist/util.cjs" + } } }, "scripts": { diff --git a/rollup.config.ts b/rollup.config.ts index 22d5101..67c2c78 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -5,30 +5,40 @@ import ts from "rollup-plugin-ts" import pkg from "./package.json" assert { type: "json" } -export default defineConfig({ - input: "src/lib.ts", +export const createBundleConfig = ( + input: string, + name: keyof typeof pkg.exports, +) => ( + defineConfig({ + input, - output: [ - { - file: pkg.exports["."].import.default, - format: "esm", - }, + output: [ + { + file: pkg.exports[name].import.default, + format: "esm", + }, + { + file: pkg.exports[name].require.default, + format: "cjs", + }, + ], - { - file: pkg.exports["."].require.default, - format: "cjs", - }, - ], + external: id => !/^[./]/.test(id), - external: id => !/^[./]/.test(id), + plugins: [ + nodeResolve(), + ts(), - plugins: [ - nodeResolve(), - ts(), + cleanup({ + comments: "jsdoc", + extensions: ["ts"], + }), + ], + }) +) - cleanup({ - comments: "jsdoc", - extensions: ["ts"], - }), - ], -}) + +export default [ + createBundleConfig("src/lib.ts", "."), + createBundleConfig("src/util/lib.ts", "./util"), +] diff --git a/src/lib.ts b/src/lib.ts index c929b01..0f31a88 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -1,5 +1,6 @@ export { abstract, expression, trait, + type Implements, type Trait, type TraitExpression } from "." diff --git a/src/util/lib.ts b/src/util/lib.ts new file mode 100644 index 0000000..4e2038a --- /dev/null +++ b/src/util/lib.ts @@ -0,0 +1,6 @@ +export { + Extend, + ExtendFn, + Extendable, + ExtendableFn +} from "." -- 2.49.1 From cf82cb668372d6e9aad5cd7e2235bb1973b25f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 6 Feb 2024 02:21:05 +0100 Subject: [PATCH 63/65] Trait helpers --- src/Trait.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 8e0d198..6d91e3b 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -1,7 +1,7 @@ -import { Fn } from "hotscript" +import { Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" import { AbstractTag, TraitExpression, emptyTraitExpression } from "." -import { StaticMembers } from "./util" +import { ExtendFn, SimplifyFn, StaticMembers } from "./util" export type AddAbstractToImplClass< @@ -104,6 +104,26 @@ export namespace Trait { export interface SupertraitsFn extends Fn { return: Trait.Supertraits } + + export type Class = ( + AbstractClass< + Trait.Instance, + any[] + > & + Pipe, [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) + + export type Instance = ( + Pipe, [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) } -- 2.49.1 From ff1f38a4a26a462b4cf720ca12b2427375c21713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 6 Feb 2024 02:52:04 +0100 Subject: [PATCH 64/65] Fixed helpers --- src/Trait.ts | 21 +++++++++++++++++---- src/tests.ts | 4 +++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 6d91e3b..39c8d26 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -1,7 +1,7 @@ import { Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" import { AbstractTag, TraitExpression, emptyTraitExpression } from "." -import { ExtendFn, SimplifyFn, StaticMembers } from "./util" +import { ExtendFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" export type AddAbstractToImplClass< @@ -110,20 +110,33 @@ export namespace Trait { Trait.Instance, any[] > & - Pipe, [ - Tuples.Map, + Pipe<[ + ...Trait.Supertraits, + T, + ], [ + Tuples.Map, + Tuples.Map, ExtendFn, SimplifyFn, ]> ) + export interface ClassFn extends Fn { + return: Trait.Class + } export type Instance = ( - Pipe, [ + Pipe<[ + ...Trait.Supertraits, + T, + ], [ Tuples.Map, ExtendFn, SimplifyFn, ]> ) + export interface InstanceFn extends Fn { + return: Trait.Instance + } } diff --git a/src/tests.ts b/src/tests.ts index c285337..f8bede5 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,4 +1,6 @@ +import { Simplify } from "type-fest" import { Implements, Trait, abstract, expression, trait } from "." +import { Pipe } from "hotscript" const PrintsHelloOnNew = trait( @@ -49,7 +51,7 @@ const ActiveStatefulSubscription = expression Super => class ActiveStatefulSubscription extends Super {}, ) -type T = Trait.OwnAbstract +type T = Trait.Instance class TestSuperclass { -- 2.49.1 From d6b173aea5488b5fb5c03aac4364a10686c84af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 6 Feb 2024 03:12:56 +0100 Subject: [PATCH 65/65] Helper fix --- src/Trait.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Trait.ts b/src/Trait.ts index 39c8d26..6018376 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -110,10 +110,7 @@ export namespace Trait { Trait.Instance, any[] > & - Pipe<[ - ...Trait.Supertraits, - T, - ], [ + Pipe<[...Trait.Supertraits, T], [ Tuples.Map, Tuples.Map, ExtendFn, @@ -125,10 +122,7 @@ export namespace Trait { } export type Instance = ( - Pipe<[ - ...Trait.Supertraits, - T, - ], [ + Pipe<[...Trait.Supertraits, T], [ Tuples.Map, ExtendFn, SimplifyFn, -- 2.49.1