From d759b2cbba171819f7e7e8fb072f9cc82dd692ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 28 Dec 2023 19:25:19 +0100 Subject: [PATCH] Moved old code to legacy/ --- src/index.ts | 82 ++++++++++++++++++++++++++++- src/legacy/tests.ts | 74 ++++++++++++++++++++++++++ src/{ => legacy}/trait.ts | 0 src/{ => legacy}/util/class.ts | 0 src/tests-inheritance.ts | 62 ---------------------- src/tests.ts | 94 +++++++++++++++------------------- src/trait-inheritance.ts | 81 ----------------------------- 7 files changed, 196 insertions(+), 197 deletions(-) create mode 100644 src/legacy/tests.ts rename src/{ => legacy}/trait.ts (100%) rename src/{ => legacy}/util/class.ts (100%) delete mode 100644 src/tests-inheritance.ts delete mode 100644 src/trait-inheritance.ts diff --git a/src/index.ts b/src/index.ts index d46d244..f852ac8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,81 @@ -export * from "./trait" +import { AbstractClass, AbstractConstructor, Opaque, UnionToIntersection } from "type-fest" + + +/** + * Represents the static members of a class. + * + * @template C - The type of the class for which static members are extracted. + * @typeparam The static members of the class. + */ +export type StaticMembers = Pick + + +export type Trait< + C extends AbstractClass +> = Opaque< + TraitApplier, + "thilatrait/Trait" +> + +export type TraitApplier< + C extends AbstractClass +> = + (Parent: AbstractConstructor) => C + +export type UnwrapTraitC = + T extends Trait + ? C + : never + + +export function trait< + C extends AbstractClass +>( + applier: TraitApplier +) { + return applier as Trait +} + + +export function extendsAndExpresses< + C extends AbstractClass, + Traits extends readonly Trait[], +>( + extend: C, + traits: Traits, +) { + return traits.reduce( + (previous, trait) => trait(previous), + extend, + ) as ( + AbstractClass< + InstanceType & + UnionToIntersection< + InstanceType< + UnwrapTraitC< + Traits[number] + > + > + >, + + ConstructorParameters + > & + + StaticMembers & + StaticMembers< + UnionToIntersection< + UnwrapTraitC< + Traits[number] + > + > + > + ) +} + +export function expresses< + Traits extends readonly Trait[], +>( + ...traits: Traits +) { + return extendsAndExpresses(Object, traits) +} diff --git a/src/legacy/tests.ts b/src/legacy/tests.ts new file mode 100644 index 0000000..e86528d --- /dev/null +++ b/src/legacy/tests.ts @@ -0,0 +1,74 @@ +import { AbstractClass } from "type-fest" +import { expresses } from "./trait" + + +function inspectClass(class_: AbstractClass) { + Object.getOwnPropertyNames(class_).forEach(name => { + console.log( + "[static]", + name, + Object.getOwnPropertyDescriptor(class_, name) + ) + }) + + Object.getOwnPropertyNames(class_.prototype).forEach(name => { + console.log( + "[prototype]", + name, + Object.getOwnPropertyDescriptor(class_.prototype, name) + ) + }) +} + + +abstract class Identified { + abstract id: ID + + equals(el: Identified) { + return this.id === el.id + } + + // initializer() { + // console.log("Identified initializer") + // } +} + +class ImplementsIdentifiable extends Identified { + id!: ID +} + + +abstract class Permissible { + static readonly defaultPermissions: string[] = [] + permissions: string[] = [] + // permissions!: string[] + + constructor() { + console.log("Permissible constructor") + } + + initializer() { + console.log("Permissible initializer") + this.permissions = [] + } +} + + +class User extends expresses( + Identified as typeof Identified, + // Identified, + Permissible, +) { + readonly id: bigint + + constructor(id: bigint) { + super() + this.id = id + } +} + +const user1 = new User(BigInt(1)) +const user2 = new User(BigInt(2)) + +console.log(user1) +console.log(user1.equals(user2)) diff --git a/src/trait.ts b/src/legacy/trait.ts similarity index 100% rename from src/trait.ts rename to src/legacy/trait.ts diff --git a/src/util/class.ts b/src/legacy/util/class.ts similarity index 100% rename from src/util/class.ts rename to src/legacy/util/class.ts diff --git a/src/tests-inheritance.ts b/src/tests-inheritance.ts deleted file mode 100644 index 8241b1a..0000000 --- a/src/tests-inheritance.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { expresses, trait } from "./trait-inheritance" - - -const Identifiable = () => - trait(Parent => { - abstract class Identified extends Parent { - abstract id: ID - - equals(el: Identified) { - return this.id === el.id - } - - constructor(...args: any[]) { - super(...args) - console.log("Identified constructor") - } - } - - return Identified - }) - -const ImplementsIdentifiable = (defaultID: ID) => - trait(Parent => { - abstract class ImplementsIdentifiable extends Identifiable()(Parent) { - id: ID = defaultID - } - - return ImplementsIdentifiable - }) - - -const Permissible = trait(Parent => { - abstract class Permissible extends Parent { - 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)) diff --git a/src/tests.ts b/src/tests.ts index e86528d..b19ad37 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,74 +1,62 @@ -import { AbstractClass } from "type-fest" -import { expresses } from "./trait" +import { expresses, trait } from "." -function inspectClass(class_: AbstractClass) { - Object.getOwnPropertyNames(class_).forEach(name => { - console.log( - "[static]", - name, - Object.getOwnPropertyDescriptor(class_, name) - ) +const Identifiable = () => + trait(Parent => { + abstract class Identified extends Parent { + abstract id: ID + + equals(el: Identified) { + return this.id === el.id + } + + constructor(...args: any[]) { + super(...args) + console.log("Identified constructor") + } + } + + return Identified }) - Object.getOwnPropertyNames(class_.prototype).forEach(name => { - console.log( - "[prototype]", - name, - Object.getOwnPropertyDescriptor(class_.prototype, name) - ) +const ImplementsIdentifiable = (defaultID: ID) => + trait(Parent => { + abstract class ImplementsIdentifiable extends Identifiable()(Parent) { + id: ID = defaultID + } + + return ImplementsIdentifiable }) -} -abstract class Identified { - abstract id: ID +const Permissible = trait(Parent => { + abstract class Permissible extends Parent { + static readonly defaultPermissions: string[] = [] + permissions: string[] = [] - equals(el: Identified) { - return this.id === el.id + constructor(...args: any[]) { + super(...args) + console.log("Permissible constructor") + } } - // initializer() { - // console.log("Identified initializer") - // } -} - -class ImplementsIdentifiable extends Identified { - id!: ID -} + return Permissible +}) -abstract class Permissible { - static readonly defaultPermissions: string[] = [] - permissions: string[] = [] - // permissions!: string[] - - constructor() { - console.log("Permissible constructor") - } - - initializer() { - console.log("Permissible initializer") - this.permissions = [] - } -} - - -class User extends expresses( - Identified as typeof Identified, - // Identified, +const UserProto = expresses( + // Identifiable(), + ImplementsIdentifiable(0n), Permissible, -) { - readonly id: bigint +) +class User extends UserProto { constructor(id: bigint) { super() this.id = id } } -const user1 = new User(BigInt(1)) -const user2 = new User(BigInt(2)) - +const user1 = new User(1n) console.log(user1) -console.log(user1.equals(user2)) +console.log(user1.equals(user1)) diff --git a/src/trait-inheritance.ts b/src/trait-inheritance.ts deleted file mode 100644 index f852ac8..0000000 --- a/src/trait-inheritance.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { AbstractClass, AbstractConstructor, Opaque, UnionToIntersection } from "type-fest" - - -/** - * Represents the static members of a class. - * - * @template C - The type of the class for which static members are extracted. - * @typeparam The static members of the class. - */ -export type StaticMembers = Pick - - -export type Trait< - C extends AbstractClass -> = Opaque< - TraitApplier, - "thilatrait/Trait" -> - -export type TraitApplier< - C extends AbstractClass -> = - (Parent: AbstractConstructor) => C - -export type UnwrapTraitC = - T extends Trait - ? C - : never - - -export function trait< - C extends AbstractClass ->( - applier: TraitApplier -) { - return applier as Trait -} - - -export function extendsAndExpresses< - C extends AbstractClass, - Traits extends readonly Trait[], ->( - extend: C, - traits: Traits, -) { - return traits.reduce( - (previous, trait) => trait(previous), - extend, - ) as ( - AbstractClass< - InstanceType & - UnionToIntersection< - InstanceType< - UnwrapTraitC< - Traits[number] - > - > - >, - - ConstructorParameters - > & - - StaticMembers & - StaticMembers< - UnionToIntersection< - UnwrapTraitC< - Traits[number] - > - > - > - ) -} - -export function expresses< - Traits extends readonly Trait[], ->( - ...traits: Traits -) { - return extendsAndExpresses(Object, traits) -}