From de3b23018ab034d614033bcd6afe28588dd6dc74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 20 Feb 2024 01:39:38 +0100 Subject: [PATCH] 0.1.4 (#4) 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/4 --- bun.lockb | Bin 155678 -> 156435 bytes package.json | 11 +- src/Trait.ts | 231 ++++++++++++++++------------------ src/TraitBuilder.ts | 121 ++++++++++++++++++ src/TraitExpression.ts | 190 +++++++++++++++++----------- src/TraitExpressionBuilder.ts | 157 +++++++++++------------ src/abstract.ts | 10 -- src/lib.ts | 6 +- src/tests.ts | 77 ++++++------ src/util/extend.ts | 84 ++++++++++--- src/util/misc.ts | 10 +- 11 files changed, 535 insertions(+), 362 deletions(-) create mode 100644 src/TraitBuilder.ts delete mode 100644 src/abstract.ts diff --git a/bun.lockb b/bun.lockb index 1aa0c800bb2453190ab6462bf94fee3e72b2f76d..0e06437060ce846cb44522095b4c044298c209f4 100755 GIT binary patch delta 24463 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 delta 24309 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, - Abstract extends {}, -> = ( - Class< - Abstract & InstanceType, - ConstructorParameters - > & - StaticMembers -) - -export type RemoveAbstractFromImplClass< - ImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, - Abstract extends {}, -> = ( - Class< - Omit, keyof Abstract>, - ConstructorParameters - > & - Omit, "_tag"> -) +import { AbstractClass, Class, Simplify } from "type-fest" +import { TraitExpression } from "./TraitExpression" +import { Extend, StaticMembers } from "./util" export class Trait< - Supertraits extends TraitExpression[], Trait[]>, - Abstract extends {}, - ImplClass extends Class<{}, []>, + SuperExpression extends TraitExpression< + typeof TraitExpression.NullSuperclass, + Trait[] + >, + Abstract extends object, + StaticAbstract extends object, + ImplClass extends AbstractClass, > { constructor( - readonly supertraits: Supertraits, - readonly abstract: Abstract, - readonly apply: (Super: AbstractClass<{}>) => ImplClass, + readonly superExpression: SuperExpression, + readonly abstract: Abstract, + readonly staticAbstract: StaticAbstract, + readonly apply: (Super: AbstractClass) => ImplClass, ) {} } export namespace Trait { - export type OwnSupertraits = ( - T extends Trait - ? Supertraits + export type SuperExpression = ( + T extends Trait + ? SuperExpression : never ) - export interface OwnSupertraitsFn extends Fn { - return: Trait.OwnSupertraits - } - export type OwnAbstract = ( - T extends Trait + export type Supertraits = ( + TraitExpression.Traits> + ) + + export type Abstract = ( + T extends Trait ? Abstract : never ) - export interface OwnAbstractFn extends Fn { - return: Trait.OwnAbstract - } - export type OwnImplClass = ( - T extends Trait + export type StaticAbstract = ( + T extends Trait + ? StaticAbstract + : never + ) + + export type ImplClass = ( + T extends Trait ? ImplClass : never ) - export interface OwnImplClassFn extends Fn { - return: Trait.OwnImplClass - } - export type OwnImplInstance = ( - T extends Trait - ? InstanceType - : never + export type ImplInstance = ( + InstanceType> ) - export interface OwnImplInstanceFn extends Fn { - return: Trait.OwnImplInstance - } - export type OwnClass = ( - T extends Trait - ? AddAbstractToImplClass - : never + export type ImplStaticMembers = ( + StaticMembers> ) - 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, - Tuples.Map, - Tuples.Map, - ExtendFn, - SimplifyFn, - ]> - ) - export interface ClassFn extends Fn { - return: Trait.Class - } export type Instance = ( - Pipe, - Tuples.Map, - ExtendFn, - SimplifyFn, + Extend<[ + Trait.Abstract, + Trait.ImplInstance, ]> ) - export interface InstanceFn extends Fn { - return: Trait.Instance + + export type Static = ( + Extend<[ + Trait.StaticAbstract, + Trait.ImplStaticMembers, + ]> + ) +} + +export namespace TraitTuple { + export type MapAbstract = { + [K in keyof T]: K extends keyof [] + ? T[K] + : Trait.Abstract + } + + export type MapStaticAbstract = { + [K in keyof T]: K extends keyof [] + ? T[K] + : Trait.StaticAbstract + } + + export type MapImplClass = { + [K in keyof T]: K extends keyof [] + ? T[K] + : Trait.ImplClass + } + + export type MapImplInstance = { + [K in keyof T]: K extends keyof [] + ? T[K] + : Trait.ImplInstance + } + + export type MapImplStaticMembers = { + [K in keyof T]: K extends keyof [] + ? T[K] + : Trait.ImplStaticMembers + } + + export type MapInstance = { + [K in keyof T]: K extends keyof [] + ? T[K] + : Trait.Instance + } + + export type MapStaticMembers = { + [K in keyof T]: K extends keyof [] + ? T[K] + : Trait.Static } } -export function trait< - Abstract extends {}, - ImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, ->( - abstract: Opaque, - apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract, -) { - return new Trait( - emptyTraitExpression, - abstract as Abstract, - apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, - ) -} +export type TraitClass> = ( + AbstractClass, any[]> & + TraitStaticMembers +) + +export type TraitConcreteClass> = ( + Class, any[]> & + TraitStaticMembers +) + +export type TraitInstance> = ( + Simplify> +) + +export type TraitStaticMembers> = ( + Simplify> +) diff --git a/src/TraitBuilder.ts b/src/TraitBuilder.ts new file mode 100644 index 0000000..a59b333 --- /dev/null +++ b/src/TraitBuilder.ts @@ -0,0 +1,121 @@ +import { AbstractClass, Simplify } from "type-fest" +import { Trait } from "./Trait" +import { TraitExpression } from "./TraitExpression" +import { Extend, StaticMembers } from "./util" + + +declare const implSuperSymbol: unique symbol + +type ImplSuper = ( + This extends TraitBuilder< + any, + infer Abstract, + infer StaticAbstract, + infer ImplClass + > + ? ( + AbstractClass< + Simplify< + Extend<[ + Abstract, + InstanceType, + ]> + > + > & + + Simplify< + Extend<[ + StaticAbstract, + StaticMembers, + ]> + > & + { readonly [implSuperSymbol]: true } + ) + : never +) + + +export class TraitBuilder< + SuperExpression extends TraitExpression< + typeof TraitExpression.NullSuperclass, + Trait[] + >, + Abstract extends object, + StaticAbstract extends object, + ImplClass extends AbstractClass, +> { + constructor( + private readonly traitSuperExpression: SuperExpression, + private readonly traitAbstract: Abstract, + private readonly traitStaticAbstract: StaticAbstract, + private readonly traitApply: (Super: AbstractClass) => ImplClass, + ) {} + + abstract( + _: (Super: AbstractClass) => AbstractClass + ) { + return new TraitBuilder( + this.traitSuperExpression, + {} as Simplify, + this.traitStaticAbstract, + this.traitApply, + ) + } + + staticAbstract( + _: (Super: AbstractClass) => AbstractClass + ) { + return new TraitBuilder( + this.traitSuperExpression, + this.traitAbstract, + {} as Simplify, + this.traitApply, + ) + } + + implement< + ImplClassWithAbstract extends ImplSuper // TODO: find a way to set the constraint to concrete classes while keeping the Super arg as an abstract class + >( + apply: (Super: ImplSuper) => ImplClassWithAbstract + ) { + return new TraitBuilder( + this.traitSuperExpression, + this.traitAbstract, + this.traitStaticAbstract, + + apply as unknown as (Super: AbstractClass) => ( + AbstractClass< + Simplify< + Omit< + InstanceType, + keyof Abstract + > + > + > & + + Simplify< + Omit< + StaticMembers, + keyof StaticAbstract | typeof implSuperSymbol + > + > + ), + ) + } + + build() { + return new Trait( + this.traitSuperExpression, + this.traitAbstract, + this.traitStaticAbstract, + this.traitApply, + ) + } +} + +export const trait = new TraitBuilder( + new TraitExpression(TraitExpression.NullSuperclass, []), + {} as object, + {} as object, + Super => class extends Super {} as AbstractClass, +) diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts index d5bfed3..2490377 100644 --- a/src/TraitExpression.ts +++ b/src/TraitExpression.ts @@ -1,113 +1,163 @@ -import { Fn, Pipe, Tuples } from "hotscript" -import { AbstractClass, Class, Opaque } from "type-fest" -import { RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "./Trait" -import { AbstractTag } from "./abstract" -import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" - - -// type RemoveSupertraitsAbstractFromAbstract = { -// [Key in Extract]: Left[Key] -// } & { -// [Key in Exclude]: Left[Key] -// } +import { AbstractClass, Class, Simplify } from "type-fest" +import { Trait, TraitTuple } from "./Trait" +import { TraitBuilder } from "./TraitBuilder" +import { Extend, StaticMembers } from "./util" export class TraitExpression< - Superclass extends AbstractClass<{}>, - const OwnTraits extends Trait[], - const AllTraits extends Trait[], + Superclass extends AbstractClass, + const Traits extends Trait[], > { constructor( readonly superclass: Superclass, - readonly ownTraits: OwnTraits, - readonly allTraits: AllTraits, + readonly traits: Traits, ) {} get extends(): ( AbstractClass< - 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 - ]>, + InstanceType & // Keep the instance of the superclass outside of any kind of type manipulation + // as it can accidentely remove abstract properties + Simplify< + Extend< + TraitTuple.MapImplInstance + > + >, ConstructorParameters > & - 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 - ]> + Simplify< + Extend<[ + StaticMembers, + ...TraitTuple.MapImplStaticMembers, + ]> + > ) { - return this.allTraits.reduce( + return this.traits.reduce( (previous, trait) => trait.apply(previous), this.superclass, ) as any } + implementsStatic(target: ImplementsStatic, context: any) {} + subtrait< - This extends TraitExpression, - SubtraitAbstract extends Implements, - SubtraitImplClassWithAbstract extends Class & { _tag: TraitApplierSuperTag }, + This extends TraitExpression >( - this: This, - abstract: (expression: This) => Opaque, - apply: (Super: AbstractClass & { _tag: TraitApplierSuperTag }) => SubtraitImplClassWithAbstract, + this: This ) { - return new Trait( + return new TraitBuilder< + This, + + Simplify< + Extend> + >, + Simplify< + Extend> + >, + + AbstractClass< + Simplify< + Extend> + > + > & + Simplify< + Extend> + > + >( this, - // {} as RemoveSupertraitsAbstractFromAbstract>, - {} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements from this. - apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + {} as any, + {} as any, + Super => class extends Super {} as any, ) } } export namespace TraitExpression { + declare const nullSuperclassSymbol: unique symbol export class NullSuperclass { - static readonly _tag = "@thilawyn/traitify-ts/TraitExpression.NullSuperclass" + static readonly [nullSuperclassSymbol]: true + constructor(...args: any[]) {} } export type Superclass = ( - T extends TraitExpression + T extends TraitExpression ? Superclass : never ) - export interface SuperclassFn extends Fn { - return: TraitExpression.Superclass - } - export type OwnTraits = ( - T extends TraitExpression - ? OwnTraits + export type Traits = ( + T extends TraitExpression + ? Traits : 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, [], []) - -export type Implements> = ( - Pipe, - ExtendFn, - SimplifyFn, - ]> +export type Implements< + Exp extends TraitExpression[]> +> = ( + Simplify< + Extend< + TraitTuple.MapAbstract< + TraitExpression.Traits + > + > + > +) + +export type ImplementsStatic< + Exp extends TraitExpression[]> +> = ( + Simplify< + Extend< + TraitTuple.MapStaticAbstract< + TraitExpression.Traits + > + > + > +) + + +export type TraitExpressionClass< + Exp extends TraitExpression[]> +> = ( + AbstractClass< + TraitExpressionInstance, + ConstructorParameters> + > & + TraitExpressionStaticMembers +) + +export type TraitExpressionConcreteClass< + Exp extends TraitExpression[]> +> = ( + Class< + TraitExpressionInstance, + ConstructorParameters> + > & + TraitExpressionStaticMembers +) + +export type TraitExpressionInstance< + Exp extends TraitExpression[]> +> = ( + InstanceType> & // Keep the instance of the superclass outside of any kind of type manipulation + // as it can accidentely remove abstract properties + Simplify< + Extend< + TraitTuple.MapInstance> + > + > +) + +export type TraitExpressionStaticMembers< + Exp extends TraitExpression[]> +> = ( + Simplify< + Extend<[ + StaticMembers>, + ...TraitTuple.MapStaticMembers>, + ]> + > ) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts index c1f5064..d1fdeec 100644 --- a/src/TraitExpressionBuilder.ts +++ b/src/TraitExpressionBuilder.ts @@ -1,129 +1,120 @@ -import { Call, Fn, Pipe, Tuples } from "hotscript" +import { uniq } from "lodash-es" import { AbstractClass } from "type-fest" -import { Trait } from "./Trait" -import { TraitExpression, emptyTraitExpression } from "./TraitExpression" -import { ExtendableFn, StaticMembersFn } from "./util" +import { Trait, TraitTuple } from "./Trait" +import { TraitExpression } from "./TraitExpression" +import { Extendable, StaticMembers } from "./util" -type SpreadSupertraits[]> = ( - Call< - Tuples.FlatMap, - Traits - > +type SpreadSupertraits = ( + T extends [infer Trait, ...infer Rest] + ? [ + ...Trait.Supertraits, + Trait, + ...SpreadSupertraits, + ] + : [] ) -interface PrependTraitSupertraitsFn extends Fn { - return: [...Trait.Supertraits, this["arg0"]] -} -type AbstractMembersExtendable< - Superclass extends AbstractClass<{}>, - Traits extends Trait[], +type InstanceExtendable< + Superclass extends AbstractClass, + Traits extends Trait[], > = ( - Pipe, - Tuples.Prepend>, + Extendable<[ + InstanceType, + ...TraitTuple.MapInstance, ]> ) -type ImplInstanceExtendable< - Superclass extends AbstractClass<{}>, - Traits extends Trait[], +type StaticMembersExtendable< + Superclass extends AbstractClass, + Traits extends Trait[], > = ( - Pipe, - Tuples.Prepend>, - ]> -) - -type ImplStaticMembersExtendable< - Superclass extends AbstractClass<{}>, - Traits extends Trait[], -> = ( - Pipe, - Tuples.Prepend, - Tuples.Map, - ExtendableFn, + Extendable<[ + StaticMembers, + ...TraitTuple.MapStaticMembers, ]> ) type BuildTraitExpression< - Superclass extends AbstractClass<{}>, - OwnTraits extends Trait[], - AllTraits extends Trait[], + Superclass extends AbstractClass, + Traits extends Trait[], > = ( - 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 + InstanceExtendable extends false + ? "Type conflict on the instance side." + : StaticMembersExtendable extends false + ? "Type conflict on the static side." + : TraitExpression ) class TraitExpressionBuilder< - Superclass extends AbstractClass<{}>, - const OwnTraits extends Trait[], - const AllTraits extends Trait[], + Superclass extends AbstractClass, + const Traits extends Trait[], > { - constructor(private expression: TraitExpression) {} + constructor( + private readonly expressionSuperclass: Superclass, + private readonly expressionTraits: Traits, + ) {} extends< - Super extends AbstractClass + Super extends AbstractClass >( superclass: Super ) { return new TraitExpressionBuilder( - new TraitExpression( - superclass, - this.expression.ownTraits, - this.expression.allTraits, - ) + superclass, + this.expressionTraits, ) } expresses< - const Traits extends Trait[] - >( - ...traits: Traits - ): TraitExpressionBuilder< - Superclass, - [...OwnTraits, ...Traits], - [...AllTraits, ...SpreadSupertraits] - > { - return new TraitExpressionBuilder( - new TraitExpression( - this.expression.superclass, - [...this.expression.ownTraits, ...traits], - [...this.expression.allTraits, ...this.spreadSupertraits(traits)], - ) - ) - } - - private spreadSupertraits< - const Traits extends Trait< - TraitExpression[]>, + const T extends Trait< + TraitExpression< + typeof TraitExpression.NullSuperclass, + Trait[] + >, + any, any, any >[] >( - traits: Traits + ...traits: T ) { - return traits.flatMap(trait => [ - ...trait.supertraits.allTraits, - trait, - ]) as SpreadSupertraits + return new TraitExpressionBuilder( + this.expressionSuperclass, + + uniq([ + ...this.expressionTraits, + ...traits.flatMap(trait => [ + ...trait.superExpression.traits, + trait, + ]), + ]) as [...Traits, ...SpreadSupertraits], + ) } build() { - return this.expression as BuildTraitExpression + return new TraitExpression( + this.expressionSuperclass, + this.expressionTraits, + ) as BuildTraitExpression } then(fn: (expression: ReturnType) => V): V { return fn(this.build()) } + + buildAnyway() { + return new TraitExpression( + this.expressionSuperclass, + this.expressionTraits, + ) + } + + thenAnyway(fn: (expression: ReturnType) => V): V { + return fn(this.buildAnyway()) + } } -export const expression = new TraitExpressionBuilder(emptyTraitExpression) +export const expression = new TraitExpressionBuilder(TraitExpression.NullSuperclass, []) diff --git a/src/abstract.ts b/src/abstract.ts deleted file mode 100644 index c6502e4..0000000 --- a/src/abstract.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Opaque } from "type-fest" - - -export type AbstractTag = "@thilawyn/traitify-ts/Abstract" - -export function abstract< - Abstract extends {} = {} ->() { - return {} as Opaque -} diff --git a/src/lib.ts b/src/lib.ts index e7f6bb7..9426d7e 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -1,4 +1,4 @@ -export { trait, type Trait } from "./Trait" -export { Implements, type TraitExpression } from "./TraitExpression" +export { Trait, TraitClass, TraitConcreteClass, TraitInstance, TraitStaticMembers, TraitTuple } from "./Trait" +export { TraitBuilder, trait } from "./TraitBuilder" +export { Implements, ImplementsStatic, TraitExpression, TraitExpressionClass, TraitExpressionConcreteClass, TraitExpressionInstance, TraitExpressionStaticMembers } from "./TraitExpression" export { expression } from "./TraitExpressionBuilder" -export { abstract } from "./abstract" diff --git a/src/tests.ts b/src/tests.ts index 7773ed8..daf516b 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,67 +1,61 @@ -import { Trait, trait } from "./Trait" -import { Implements } from "./TraitExpression" +import { TraitClass } from "./Trait" +import { trait } from "./TraitBuilder" +import { Implements, ImplementsStatic, TraitExpressionClass } from "./TraitExpression" import { expression } from "./TraitExpressionBuilder" -import { abstract } from "./abstract" -const PrintsHelloOnNew = trait( - abstract(), - Super => class PrintsHelloOnNew extends Super { +const PrintsHelloOnNew = trait + .implement(Super => class PrintsHelloOnNew extends Super { static readonly isPrintsHelloOnNew = true constructor(...args: any[]) { super(...args) console.log("Hello!") } - }, -) -type PrintsHelloOnNewClass = Trait.Class + }) + .build() -const Identifiable = () => trait( - abstract<{ readonly id: ID }>(), - Super => class Identifiable extends Super { +type PrintsHelloOnNewClass = TraitClass + +const Identifiable = () => trait + .abstract(Super => class extends Super { + declare readonly id: ID + }) + .implement(Super => class Identifiable extends Super { equals(el: Identifiable) { return this.id === el.id } - }, -) + }) + .build() -const StatefulSubscription = trait( - abstract<{ - readonly isStatefulSubscription: true - readonly status: ( +const StatefulSubscription = trait + .abstract(Super => class extends Super { + declare readonly isStatefulSubscription: true + declare readonly status: ( { _tag: "awaitingPayment" } | { _tag: "active", activeSince: Date, expiresAt?: Date } | { _tag: "expired", expiredSince: Date } ) - }>(), + }) + .build() - Super => class StatefulSubscription extends Super {}, -) -type StatefulSubscriptionClass = Trait.Class +type StatefulSubscriptionClass = TraitClass const ActiveStatefulSubscription = expression .expresses(StatefulSubscription) .build() - .subtrait( - exp => { - interface IActiveStatefulSubscription extends Implements { - readonly isActiveStatefulSubscription: true - readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } - } - - return abstract() - }, - - Super => class ActiveStatefulSubscription extends Super {}, - ) - -type ActiveStatefulSubscriptionClass = Trait.Class + .subtrait() + .abstract(Super => class extends Super { + declare readonly isActiveStatefulSubscription: true + declare readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } + }) + .build() +type ActiveStatefulSubscriptionClass = TraitClass class TestSuperclass { // id: number = 69 - // static test = 69 + static test = 69 } const exp = expression @@ -75,7 +69,10 @@ const exp = expression .build() type Abs = Implements +type AbsStatic = ImplementsStatic +type ExpClass = TraitExpressionClass +@exp.implementsStatic class User extends exp.extends implements Implements { readonly isStatefulSubscription: true = true readonly isActiveStatefulSubscription: true = true @@ -84,3 +81,9 @@ class User extends exp.extends implements Implements { } console.log(new User()) + + +// type T = NonExtendableKeys<[ +// { prout: "gneugneu" }, +// { prout: string }, +// ]> diff --git a/src/util/extend.ts b/src/util/extend.ts index d675de5..1618656 100644 --- a/src/util/extend.ts +++ b/src/util/extend.ts @@ -1,25 +1,71 @@ -import { Call, ComposeLeft, Fn, Match, Tuples } from "hotscript" import { CommonKeys } from "." -type ExtendReducer = ( - Pick> extends Pick> - ? Omit> & Self - : never +// type ExtendReducer = ( +// Pick> extends Pick> +// ? Omit> & Self +// : never +// ) +// interface ExtendReducerFn extends Fn { +// return: ExtendReducer +// } +// export type ExtendFn = Tuples.Reduce + +// export type ExtendableFn = ComposeLeft<[ +// ExtendFn, +// Match<[ +// Match.With, +// Match.With, +// ]> +// ]> + + +// TODO: use OverrideProperties from type-fest? +export type Extend = ( + T extends [ + infer Super, + infer Self, + ...infer Rest extends object[], + ] + ? Pick> extends Pick> + ? Extend<[ + Omit> & Self, + ...Rest, + ]> + : never + : T extends [infer Self] + ? Self + : {} ) -interface ExtendReducerFn extends Fn { - return: ExtendReducer -} -export type ExtendFn = Tuples.Reduce -export type Extend = Call +export type Extendable = ( + T extends [ + infer Super, + infer Self, + ...infer Rest extends object[], + ] + ? Pick> extends Pick> + ? Extendable<[ + Omit> & Self, + ...Rest, + ]> + : false + : true +) - -export type ExtendableFn = ComposeLeft<[ - ExtendFn, - Match<[ - Match.With, - Match.With, - ]> -]> -export type Extendable = Call +export type NonExtendableKeys = ( + T extends [ + infer Super extends object, + infer Self extends object, + ...infer Rest extends object[], + ] + ? {[K in keyof Super & keyof Self]: Self[K] extends Super[K] + ? never + : K + }[keyof Super & keyof Self] + | NonExtendableKeys<[ + Super & Self, + ...Rest, + ]> + : void +) diff --git a/src/util/misc.ts b/src/util/misc.ts index 3e19396..175ddfd 100644 --- a/src/util/misc.ts +++ b/src/util/misc.ts @@ -1,5 +1,4 @@ -import { Fn } from "hotscript" -import { AbstractClass, Simplify } from "type-fest" +import { AbstractClass } from "type-fest" /** @@ -9,10 +8,6 @@ import { AbstractClass, Simplify } from "type-fest" */ export type CommonKeys = Extract -export interface SimplifyFn extends Fn { - return: Simplify -} - /** * Represents the static members of a class. * @template Class - A class extending AbstractClass. @@ -20,6 +15,3 @@ export interface SimplifyFn extends Fn { export type StaticMembers> = ( Omit ) -export interface StaticMembersFn extends Fn { - return: StaticMembers -}