diff --git a/bun.lockb b/bun.lockb index 1263665..1aa0c80 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index acb7aa9..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": { @@ -28,7 +38,8 @@ "clean:node": "rm -rf node_modules" }, "dependencies": { - "type-fest": "^4.10.1" + "hotscript": "^1.0.13", + "type-fest": "^4.10.2" }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.2.3", diff --git a/rollup.config.ts b/rollup.config.ts index bca2cda..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/index.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/Trait.ts b/src/Trait.ts new file mode 100644 index 0000000..6018376 --- /dev/null +++ b/src/Trait.ts @@ -0,0 +1,153 @@ +import { Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass, Class, Opaque } from "type-fest" +import { AbstractTag, TraitExpression, emptyTraitExpression } from "." +import { ExtendFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" + + +export type AddAbstractToImplClass< + ImplClass extends Class<{}, []>, + Abstract extends {}, +> = ( + Class< + Abstract & InstanceType, + ConstructorParameters + > & + StaticMembers +) + +export type RemoveAbstractFromImplClass< + ImplClassWithAbstract extends Class, + Abstract extends {}, +> = ( + Class< + Omit, keyof Abstract>, + ConstructorParameters + > & + StaticMembers +) + + +export class Trait< + Supertraits extends TraitExpression[], Trait[]>, + Abstract extends {}, + ImplClass extends Class<{}, []>, +> { + constructor( + 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 + : never + ) + export interface OwnAbstractFn extends Fn { + return: Trait.OwnAbstract + } + + export type OwnImplClass = ( + T extends Trait + ? ImplClass + : never + ) + export interface OwnImplClassFn extends Fn { + return: Trait.OwnImplClass + } + + export type OwnImplInstance = ( + T extends Trait + ? InstanceType + : never + ) + export interface OwnImplInstanceFn extends Fn { + return: Trait.OwnImplInstance + } + + export type OwnClass = ( + T extends Trait + ? AddAbstractToImplClass + : never + ) + export interface OwnClassFn extends Fn { + return: Trait.OwnClass + } + + export type OwnInstance = ( + T extends Trait + ? InstanceType< + AddAbstractToImplClass + > + : never + ) + export interface OwnInstanceFn extends Fn { + return: Trait.OwnInstance + } + + export type Supertraits = ( + T extends Trait + ? TraitExpression.AllTraits + : never + ) + export interface SupertraitsFn extends Fn { + return: Trait.Supertraits + } + + export type Class = ( + AbstractClass< + Trait.Instance, + any[] + > & + Pipe<[...Trait.Supertraits, T], [ + Tuples.Map, + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) + export interface ClassFn extends Fn { + return: Trait.Class + } + + export type Instance = ( + Pipe<[...Trait.Supertraits, T], [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) + export interface InstanceFn extends Fn { + return: Trait.Instance + } +} + + +export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" + +export function trait< + Abstract extends {}, + ImplClassWithAbstract extends Class, +>( + abstract: Opaque, + apply: (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ), +) { + return new Trait( + emptyTraitExpression, + abstract as Abstract, + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + ) +} diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts new file mode 100644 index 0000000..9bbdbb2 --- /dev/null +++ b/src/TraitExpression.ts @@ -0,0 +1,117 @@ +import { Call, Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass, Class, Opaque } from "type-fest" +import { AbstractTag, RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "." +import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" + + +// type RemoveSupertraitsAbstractFromAbstract = { +// [Key in Extract]: Left[Key] +// } & { +// [Key in Exclude]: Left[Key] +// } + + +export class TraitExpression< + Superclass extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], +> { + constructor( + readonly superclass: Superclass, + readonly ownTraits: OwnTraits, + readonly allTraits: AllTraits, + ) {} + + get extends(): ( + AbstractClass< + Pipe<[ + InstanceType, + ...Call, AllTraits>, + ], [ + ExtendFn, + SimplifyFn, + ]>, + + ConstructorParameters + > & + + Pipe<[ + Superclass, + ...Call, AllTraits>, + ], [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) { + return this.allTraits.reduce( + (previous, trait) => trait.apply(previous), + this.superclass as Opaque, + ) as any + } + + subtrait< + SubtraitAbstract extends Implements, + SubtraitImplClassWithAbstract extends Class, + >( + abstract: (expression: typeof this) => Opaque, + apply: (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ), + ) { + return new Trait( + this, + // {} as RemoveSupertraitsAbstractFromAbstract>, + {} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements from this. + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + ) + } +} + +export namespace TraitExpression { + export class NullSuperclass {} + + export type Superclass = ( + T extends TraitExpression + ? Superclass + : never + ) + export interface SuperclassFn extends Fn { + return: TraitExpression.Superclass + } + + export type OwnTraits = ( + T extends TraitExpression + ? OwnTraits + : never + ) + export interface OwnTraitsFn extends Fn { + return: TraitExpression.OwnTraits + } + + export type AllTraits = ( + T extends TraitExpression + ? AllTraits + : never + ) + export interface AllTraitsFn extends Fn { + return: TraitExpression.AllTraits + } +} + +export const emptyTraitExpression = new TraitExpression( + TraitExpression.NullSuperclass, + [] as const, + [] as const, +) + + +export type Implements> = ( + Exp extends TraitExpression + ? Pipe, + ExtendFn, + SimplifyFn, + ]> + : never +) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts new file mode 100644 index 0000000..a4b5b67 --- /dev/null +++ b/src/TraitExpressionBuilder.ts @@ -0,0 +1,131 @@ +import { Call, Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass } from "type-fest" +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[], + AllTraits extends Trait[], +> { + constructor(private expression: TraitExpression) {} + + extends< + Super extends AbstractClass + >( + superclass: Super + ) { + return new TraitExpressionBuilder( + new TraitExpression( + superclass, + this.expression.ownTraits, + this.expression.allTraits, + ) + ) + } + + expresses< + 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 const, + ) + ) as any + } + + private spreadSupertraits< + Traits extends Trait< + TraitExpression[]>, + any, + any + >[] + >( + traits: Traits + ) { + return traits.flatMap(trait => [ + ...trait.supertraits.allTraits, + trait, + ]) as SpreadSupertraits + } + + build() { + return this.expression as BuildTraitExpression + } + + then(fn: (expression: ReturnType) => V): V { + return fn(this.build()) + } +} + +export const expression = new TraitExpressionBuilder(emptyTraitExpression) diff --git a/src/abstract.ts b/src/abstract.ts new file mode 100644 index 0000000..c6502e4 --- /dev/null +++ b/src/abstract.ts @@ -0,0 +1,10 @@ +import { Opaque } from "type-fest" + + +export type AbstractTag = "@thilawyn/traitify-ts/Abstract" + +export function abstract< + Abstract extends {} = {} +>() { + return {} as Opaque +} diff --git a/src/expresses.ts b/src/expresses.ts deleted file mode 100644 index 5784e56..0000000 --- a/src/expresses.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { AbstractClass, Opaque } from "type-fest" -import { Trait, TraitApplierSuperTag } from "." -import { ClassesInstances, ClassesStaticMembers, MergeInheritanceTree, MergeInheritanceTreeWithoutOverriding, StaticMembers, TraitsClasses } from "./util" - - -/** - * 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[], ->( - extend: C, - ...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 - >, - ]> - ) -} - -/** - * 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 - * } - * } - * ``` - */ -export function expresses< - Traits extends readonly Trait[], ->( - ...traits: Traits -) { - return extendsAndExpresses(Object, ...traits) -} diff --git a/src/index.ts b/src/index.ts index ae86066..bf1c52b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,4 @@ -export * from "./expresses" -export * from "./trait" +export * from "./Trait" +export * from "./TraitExpression" +export * from "./TraitExpressionBuilder" +export * from "./abstract" diff --git a/src/lib.ts b/src/lib.ts new file mode 100644 index 0000000..0f31a88 --- /dev/null +++ b/src/lib.ts @@ -0,0 +1,6 @@ +export { + abstract, expression, trait, + type Implements, + type Trait, + type TraitExpression +} from "." diff --git a/src/tests.ts b/src/tests.ts index cff84f8..f8bede5 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,131 +1,81 @@ -import { AbstractClass } from "type-fest" -import { expresses, extendsAndExpresses, trait } from "." -import { ClassesInstances, MergeInheritanceTree } from "./util" +import { Simplify } from "type-fest" +import { Implements, Trait, abstract, expression, trait } from "." +import { Pipe } from "hotscript" -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[] = [] - +const PrintsHelloOnNew = trait( + abstract(), + Super => class PrintsHelloOnNew extends Super { constructor(...args: any[]) { super(...args) - console.log("Permissible constructor") + console.log("Hello!") } - } - - return Permissible -}) - - -const UserProto = expresses( - // Identifiable(), - ImplementsIdentifiable(0n), - Permissible, + }, ) -class User extends UserProto { - constructor(id: bigint) { - super() - this.id = id - } -} +const Identifiable = () => trait( + abstract<{ readonly id: ID }>(), + Super => class Identifiable extends Super { + equals(el: Identifiable) { + return this.id === el.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: ( +const StatefulSubscription = trait( + abstract<{ + readonly isStatefulSubscription: true + readonly status: ( { _tag: "awaitingPayment" } | { _tag: "active", activeSince: Date, expiresAt?: Date } | { _tag: "expired", expiredSince: Date } ) - } + }>(), - return Test1 -}) + Super => class StatefulSubscription extends Super {}, +) -const Test2 = trait(Super => { - abstract class Test2 extends Super { - declare 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 } + } - return Test2 -}) + return abstract() + }, -const Test3 = trait(Super => { - abstract class Test3 extends Super { - declare static testValue: { _tag: "type2", value: number } - declare lol: 10n - } + Super => class ActiveStatefulSubscription extends Super {}, + ) - return Test3 -}) - -const TestObjectProto = expresses(Test1, Test2, Test3) -TestObjectProto.testValue +type T = Trait.Instance -interface Gneugneu { - ahi: string - get adolf(): string +class TestSuperclass { + // id: number = 69 + // static test = 69 } -class GneugneuImpl implements Gneugneu { - ahi: string = "" - get adolf(): string { - throw new Error("Method not implemented.") - } +const exp = expression + .extends(TestSuperclass) + .expresses( + PrintsHelloOnNew, + Identifiable(), + // Identifiable(), + ActiveStatefulSubscription, + ) + .build() +type Abs = Implements + +class User extends exp.extends implements Implements { + readonly isStatefulSubscription: true = true + readonly isActiveStatefulSubscription: true = true + declare status: { _tag: "active"; activeSince: Date; expiresAt?: Date | undefined } + id: bigint = -1n } -abstract class Issou extends GneugneuImpl implements Gneugneu { -} +console.log(new User()) diff --git a/src/trait.ts b/src/trait.ts deleted file mode 100644 index 21fd00c..0000000 --- a/src/trait.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { AbstractClass, AbstractConstructor, Opaque } from "type-fest" - - -/** - * 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 -> = ( - (Super: Opaque, TraitApplierSuperTag>) => Opaque -) - -/** - * 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 function trait< - C extends AbstractClass ->( - applier: TraitApplier -) { - return applier as Trait -} - -/** - * 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 -) diff --git a/src/util/class.ts b/src/util/class.ts deleted file mode 100644 index 325aba5..0000000 --- a/src/util/class.ts +++ /dev/null @@ -1,66 +0,0 @@ -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. - */ -export type StaticMembers> = ( - Omit -) - -/** - * 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 - : {} -) diff --git a/src/util/extend.ts b/src/util/extend.ts new file mode 100644 index 0000000..d675de5 --- /dev/null +++ b/src/util/extend.ts @@ -0,0 +1,25 @@ +import { Call, ComposeLeft, Fn, Match, Tuples } from "hotscript" +import { CommonKeys } from "." + + +type ExtendReducer = ( + Pick> extends Pick> + ? Omit> & Self + : never +) +interface ExtendReducerFn extends Fn { + return: ExtendReducer +} + +export type ExtendFn = Tuples.Reduce +export type Extend = Call + + +export type ExtendableFn = ComposeLeft<[ + ExtendFn, + Match<[ + Match.With, + Match.With, + ]> +]> +export type Extendable = Call diff --git a/src/util/index.ts b/src/util/index.ts index c5faea6..720a972 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" +export * from "./misc" 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/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 "." diff --git a/src/util/misc.ts b/src/util/misc.ts new file mode 100644 index 0000000..3e19396 --- /dev/null +++ b/src/util/misc.ts @@ -0,0 +1,25 @@ +import { Fn } from "hotscript" +import { AbstractClass, 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 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 +} diff --git a/src/util/trait.ts b/src/util/trait.ts deleted file mode 100644 index 149599d..0000000 --- a/src/util/trait.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Trait, TraitClass } from ".." - - -/** - * Represents an array of classes corresponding to the provided traits. - * @template Traits - An array of traits extending Trait. - */ -export type TraitsClasses[]> = ( - Traits extends [infer T, ...infer Rest] - ? T extends Trait - ? Rest extends Trait[] - ? [TraitClass, ...TraitsClasses] - : never - : never - : [] -)