From c1c3c0752463a22f9fd045e134b4f782ab30f861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 8 Feb 2024 20:01:16 +0100 Subject: [PATCH] 0.1.3 (#3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Julien Valverdé Reviewed-on: https://git.jvalver.de/Thilawyn/traitify-ts/pulls/3 --- package.json | 12 +----- rollup.config.ts | 1 - src/Trait.ts | 28 ++++++++------ src/TraitExpression.ts | 72 +++++++++++++++++------------------ src/TraitExpressionBuilder.ts | 60 ++++++++++++++--------------- src/index.ts | 4 -- src/lib.ts | 7 ++-- src/tests.ts | 13 +++++-- src/util/index.ts | 1 - src/util/lib.ts | 6 --- 10 files changed, 93 insertions(+), 111 deletions(-) delete mode 100644 src/index.ts delete mode 100644 src/util/lib.ts diff --git a/package.json b/package.json index 3826504..1b4681c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thilawyn/traitify-ts", - "version": "0.1.1", + "version": "0.1.3", "type": "module", "publishConfig": { "registry": "https://git.jvalver.de/api/packages/thilawyn/npm/" @@ -18,16 +18,6 @@ "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 67c2c78..a9e1bd7 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -40,5 +40,4 @@ export const createBundleConfig = ( export default [ createBundleConfig("src/lib.ts", "."), - createBundleConfig("src/util/lib.ts", "./util"), ] diff --git a/src/Trait.ts b/src/Trait.ts index 6018376..84516b2 100644 --- a/src/Trait.ts +++ b/src/Trait.ts @@ -1,9 +1,13 @@ import { Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, TraitExpression, emptyTraitExpression } from "." +import { TraitExpression, emptyTraitExpression } from "./TraitExpression" +import { AbstractTag } from "./abstract" import { ExtendFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" +export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" + + export type AddAbstractToImplClass< ImplClass extends Class<{}, []>, Abstract extends {}, @@ -16,14 +20,14 @@ export type AddAbstractToImplClass< ) export type RemoveAbstractFromImplClass< - ImplClassWithAbstract extends Class, + ImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, Abstract extends {}, > = ( Class< Omit, keyof Abstract>, ConstructorParameters > & - StaticMembers + Omit, "_tag"> ) @@ -110,7 +114,9 @@ export namespace Trait { Trait.Instance, any[] > & - Pipe<[...Trait.Supertraits, T], [ + Pipe, Tuples.Map, Tuples.Map, ExtendFn, @@ -122,7 +128,9 @@ export namespace Trait { } export type Instance = ( - Pipe<[...Trait.Supertraits, T], [ + Pipe, Tuples.Map, ExtendFn, SimplifyFn, @@ -134,16 +142,12 @@ export namespace Trait { } -export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" - export function trait< Abstract extends {}, - ImplClassWithAbstract extends Class, + ImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, >( - abstract: Opaque, - apply: (Super: Opaque, TraitApplierSuperTag>) => ( - Opaque - ), + abstract: Opaque, + apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract, ) { return new Trait( emptyTraitExpression, diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index 9bbdbb2..d5bfed3 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,6 +1,7 @@ -import { Call, Fn, Pipe, Tuples } from "hotscript" +import { Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" -import { AbstractTag, RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "." +import { RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "./Trait" +import { AbstractTag } from "./abstract" import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" @@ -12,9 +13,9 @@ import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpression< - Superclass extends AbstractClass<{}>, - OwnTraits extends Trait[], - AllTraits extends Trait[], + Superclass extends AbstractClass<{}>, + const OwnTraits extends Trait[], + const AllTraits extends Trait[], > { constructor( readonly superclass: Superclass, @@ -24,40 +25,38 @@ export class TraitExpression< get extends(): ( AbstractClass< - Pipe<[ - InstanceType, - ...Call, AllTraits>, - ], [ - ExtendFn, - SimplifyFn, + Pipe, // Map all the traits to the instance of their implementation class + Tuples.Prepend>, // Add the instance of the superclass at the top of the list + ExtendFn, // Reduce to a single instance that extends all the instances in the list + SimplifyFn, // Make readable for IDEs ]>, ConstructorParameters > & - Pipe<[ - Superclass, - ...Call, AllTraits>, - ], [ - Tuples.Map, - ExtendFn, - SimplifyFn, + Pipe, // Map all the traits to their implementation class + Tuples.Prepend, // Add the superclass at the top of the list + Tuples.Map, // Map all the classes to an object containing their static members + ExtendFn, // Reduce to a single object that extends all the objects in the list + SimplifyFn, // Make readable for IDEs ]> ) { return this.allTraits.reduce( (previous, trait) => trait.apply(previous), - this.superclass as Opaque, + this.superclass, ) as any } subtrait< - SubtraitAbstract extends Implements, - SubtraitImplClassWithAbstract extends Class, + This extends TraitExpression, + SubtraitAbstract extends Implements, + SubtraitImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, >( - abstract: (expression: typeof this) => Opaque, - apply: (Super: Opaque, TraitApplierSuperTag>) => ( - Opaque - ), + this: This, + abstract: (expression: This) => Opaque, + apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => SubtraitImplClassWithAbstract, ) { return new Trait( this, @@ -69,7 +68,9 @@ export class TraitExpression< } export namespace TraitExpression { - export class NullSuperclass {} + export class NullSuperclass { + static readonly _tag = "@thilawyn/traitify-ts/TraitExpression.NullSuperclass" + } export type Superclass = ( T extends TraitExpression @@ -99,19 +100,14 @@ export namespace TraitExpression { } } -export const emptyTraitExpression = new TraitExpression( - TraitExpression.NullSuperclass, - [] as const, - [] as const, -) +export const emptyTraitExpression = new TraitExpression(TraitExpression.NullSuperclass, [], []) export type Implements> = ( - Exp extends TraitExpression - ? Pipe, - ExtendFn, - SimplifyFn, - ]> - : never + Pipe, + ExtendFn, + SimplifyFn, + ]> ) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index a4b5b67..c1f5064 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -1,6 +1,7 @@ import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass } from "type-fest" -import { Trait, TraitExpression, emptyTraitExpression } from "." +import { Trait } from "./Trait" +import { TraitExpression, emptyTraitExpression } from "./TraitExpression" import { ExtendableFn, StaticMembersFn } from "./util" @@ -19,9 +20,9 @@ type AbstractMembersExtendable< Superclass extends AbstractClass<{}>, Traits extends Trait[], > = ( - Call, - ...Call, Traits>, + Pipe, + Tuples.Prepend>, ]> ) @@ -29,9 +30,9 @@ type ImplInstanceExtendable< Superclass extends AbstractClass<{}>, Traits extends Trait[], > = ( - Call, - ...Call, Traits>, + Pipe, + Tuples.Prepend>, ]> ) @@ -39,10 +40,9 @@ type ImplStaticMembersExtendable< Superclass extends AbstractClass<{}>, Traits extends Trait[], > = ( - Pipe<[ - Superclass, - ...Call, Traits>, - ], [ + Pipe, + Tuples.Prepend, Tuples.Map, ExtendableFn, ]> @@ -53,24 +53,22 @@ type BuildTraitExpression< 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 + 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[], - AllTraits extends Trait[], + Superclass extends AbstractClass<{}>, + const OwnTraits extends Trait[], + const AllTraits extends Trait[], > { - constructor(private expression: TraitExpression) {} + constructor(private expression: TraitExpression) {} extends< Super extends AbstractClass @@ -87,25 +85,25 @@ class TraitExpressionBuilder< } expresses< - Traits extends Trait[] + const Traits extends Trait[] >( ...traits: Traits ): TraitExpressionBuilder< - Super, + Superclass, [...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 const, + [...this.expression.ownTraits, ...traits], + [...this.expression.allTraits, ...this.spreadSupertraits(traits)], ) - ) as any + ) } private spreadSupertraits< - Traits extends Trait< + const Traits extends Trait< TraitExpression[]>, any, any @@ -120,7 +118,7 @@ class TraitExpressionBuilder< } build() { - return this.expression as BuildTraitExpression + return this.expression as BuildTraitExpression } then(fn: (expression: ReturnType) => V): V { diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index bf1c52b..0000000 --- a/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./Trait" -export * from "./TraitExpression" -export * from "./TraitExpressionBuilder" -export * from "./abstract" diff --git a/src/lib.ts b/src/lib.ts index 9c96c68..e7f6bb7 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -1,3 +1,4 @@ -export { - AbstractTag, Implements, TraitApplierSuperTag, abstract, expression, trait, type Trait, type TraitExpression -} from "." +export { trait, type Trait } from "./Trait" +export { Implements, type TraitExpression } from "./TraitExpression" +export { expression } from "./TraitExpressionBuilder" +export { abstract } from "./abstract" diff --git a/src/tests.ts b/src/tests.ts index f8bede5..7773ed8 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,17 +1,21 @@ -import { Simplify } from "type-fest" -import { Implements, Trait, abstract, expression, trait } from "." -import { Pipe } from "hotscript" +import { Trait, trait } from "./Trait" +import { Implements } from "./TraitExpression" +import { expression } from "./TraitExpressionBuilder" +import { abstract } from "./abstract" const PrintsHelloOnNew = trait( abstract(), Super => class PrintsHelloOnNew extends Super { + static readonly isPrintsHelloOnNew = true + constructor(...args: any[]) { super(...args) console.log("Hello!") } }, ) +type PrintsHelloOnNewClass = Trait.Class const Identifiable = () => trait( abstract<{ readonly id: ID }>(), @@ -34,6 +38,7 @@ const StatefulSubscription = trait( Super => class StatefulSubscription extends Super {}, ) +type StatefulSubscriptionClass = Trait.Class const ActiveStatefulSubscription = expression .expresses(StatefulSubscription) @@ -51,7 +56,7 @@ const ActiveStatefulSubscription = expression Super => class ActiveStatefulSubscription extends Super {}, ) -type T = Trait.Instance +type ActiveStatefulSubscriptionClass = Trait.Class class TestSuperclass { diff --git a/src/util/index.ts b/src/util/index.ts index 720a972..b529558 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1,3 +1,2 @@ export * from "./extend" -export * from "./inheritance" export * from "./misc" diff --git a/src/util/lib.ts b/src/util/lib.ts deleted file mode 100644 index 4e2038a..0000000 --- a/src/util/lib.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { - Extend, - ExtendFn, - Extendable, - ExtendableFn -} from "."