Static abstract
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Julien Valverdé
2024-02-09 14:30:10 +01:00
parent 1a88ceb296
commit e31ddeaa6e
4 changed files with 81 additions and 50 deletions

View File

@@ -11,41 +11,50 @@ export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper"
export type AddAbstractToImplClass< export type AddAbstractToImplClass<
ImplClass extends Class<{}, []>, ImplClass extends Class<{}, []>,
Abstract extends {}, Abstract extends {},
StaticAbstract extends {},
> = ( > = (
Class< Class<
Abstract & InstanceType<ImplClass>, Abstract & InstanceType<ImplClass>,
ConstructorParameters<ImplClass> ConstructorParameters<ImplClass>
> & > &
StaticAbstract &
StaticMembers<ImplClass> StaticMembers<ImplClass>
) )
export type RemoveAbstractFromImplClass< export type RemoveAbstractFromImplClass<
ImplClassWithAbstract extends Class<Abstract, []> & { _tag: TraitApplierSuperTag }, ImplClassWithAbstract extends Class<Abstract, []> & { _tag: TraitApplierSuperTag },
Abstract extends {}, Abstract extends {},
StaticAbstract extends {},
> = ( > = (
Class< Class<
Omit<InstanceType<ImplClassWithAbstract>, keyof Abstract>, Omit<InstanceType<ImplClassWithAbstract>, keyof Abstract>,
ConstructorParameters<ImplClassWithAbstract> ConstructorParameters<ImplClassWithAbstract>
> & > &
Omit<StaticMembers<ImplClassWithAbstract>, "_tag"> Omit<StaticMembers<ImplClassWithAbstract>, keyof StaticAbstract | "_tag">
) )
export class Trait< export class Trait<
Supertraits extends TraitExpression<typeof TraitExpression.NullSuperclass, Trait<any, any, any>[], Trait<any, any, any>[]>, Supertraits extends TraitExpression<
typeof TraitExpression.NullSuperclass,
Trait<any, any, any, any>[],
Trait<any, any, any, any>[]
>,
Abstract extends {}, Abstract extends {},
StaticAbstract extends {},
ImplClass extends Class<{}, []>, ImplClass extends Class<{}, []>,
> { > {
constructor( constructor(
readonly supertraits: Supertraits, readonly supertraits: Supertraits,
readonly abstract: Abstract, readonly abstract: Abstract,
readonly staticAbstract: StaticAbstract,
readonly apply: (Super: AbstractClass<{}>) => ImplClass, readonly apply: (Super: AbstractClass<{}>) => ImplClass,
) {} ) {}
} }
export namespace Trait { export namespace Trait {
export type OwnSupertraits<T> = ( export type OwnSupertraits<T> = (
T extends Trait<infer Supertraits, any, any> T extends Trait<infer Supertraits, any, any, any>
? Supertraits ? Supertraits
: never : never
) )
@@ -54,7 +63,7 @@ export namespace Trait {
} }
export type OwnAbstract<T> = ( export type OwnAbstract<T> = (
T extends Trait<any, infer Abstract, any> T extends Trait<any, infer Abstract, any, any>
? Abstract ? Abstract
: never : never
) )
@@ -62,8 +71,17 @@ export namespace Trait {
return: Trait.OwnAbstract<this["arg0"]> return: Trait.OwnAbstract<this["arg0"]>
} }
export type OwnStaticAbstract<T> = (
T extends Trait<any, any, infer StaticAbstract, any>
? StaticAbstract
: never
)
export interface OwnStaticAbstractFn extends Fn {
return: Trait.OwnAbstract<this["arg0"]>
}
export type OwnImplClass<T> = ( export type OwnImplClass<T> = (
T extends Trait<any, any, infer ImplClass> T extends Trait<any, any, any, infer ImplClass>
? ImplClass ? ImplClass
: never : never
) )
@@ -72,38 +90,28 @@ export namespace Trait {
} }
export type OwnImplInstance<T> = ( export type OwnImplInstance<T> = (
T extends Trait<any, any, infer ImplClass> InstanceType<Trait.OwnImplClass<T>>
? InstanceType<ImplClass>
: never
) )
export interface OwnImplInstanceFn extends Fn { export interface OwnImplInstanceFn extends Fn {
return: Trait.OwnImplInstance<this["arg0"]> return: Trait.OwnImplInstance<this["arg0"]>
} }
export type OwnClass<T> = ( export type OwnClass<T> = (
T extends Trait<any, infer Abstract, infer ImplClass> AddAbstractToImplClass<Trait.OwnImplClass<T>, Trait.OwnAbstract<T>, Trait.OwnStaticAbstract<T>>
? AddAbstractToImplClass<ImplClass, Abstract>
: never
) )
export interface OwnClassFn extends Fn { export interface OwnClassFn extends Fn {
return: Trait.OwnClass<this["arg0"]> return: Trait.OwnClass<this["arg0"]>
} }
export type OwnInstance<T> = ( export type OwnInstance<T> = (
T extends Trait<any, infer Abstract, infer ImplClass> InstanceType<Trait.OwnClass<T>>
? InstanceType<
AddAbstractToImplClass<ImplClass, Abstract>
>
: never
) )
export interface OwnInstanceFn extends Fn { export interface OwnInstanceFn extends Fn {
return: Trait.OwnInstance<this["arg0"]> return: Trait.OwnInstance<this["arg0"]>
} }
export type Supertraits<T> = ( export type Supertraits<T> = (
T extends Trait<infer Supertraits, any, any> TraitExpression.AllTraits<Trait.OwnSupertraits<T>>
? TraitExpression.AllTraits<Supertraits>
: never
) )
export interface SupertraitsFn extends Fn { export interface SupertraitsFn extends Fn {
return: Trait.Supertraits<this["arg0"]> return: Trait.Supertraits<this["arg0"]>
@@ -144,14 +152,17 @@ export namespace Trait {
export function trait< export function trait<
Abstract extends {}, Abstract extends {},
StaticAbstract extends {},
ImplClassWithAbstract extends Class<Abstract, []> & { _tag: TraitApplierSuperTag }, ImplClassWithAbstract extends Class<Abstract, []> & { _tag: TraitApplierSuperTag },
>( >(
abstract: Opaque<Abstract, AbstractTag>, abstract: Opaque<Abstract, AbstractTag>,
staticAbstract: Opaque<StaticAbstract, AbstractTag>,
apply: (Super: AbstractClass<Abstract> & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract, apply: (Super: AbstractClass<Abstract> & { _tag: TraitApplierSuperTag }) => ImplClassWithAbstract,
) { ) {
return new Trait( return new Trait(
emptyTraitExpression, emptyTraitExpression,
abstract as Abstract, abstract as Abstract,
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<ImplClassWithAbstract, Abstract>, staticAbstract as StaticAbstract,
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<ImplClassWithAbstract, Abstract, StaticAbstract>,
) )
} }

View File

@@ -14,8 +14,8 @@ import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util"
export class TraitExpression< export class TraitExpression<
Superclass extends AbstractClass<{}>, Superclass extends AbstractClass<{}>,
const OwnTraits extends Trait<any, any, any>[], const OwnTraits extends Trait<any, any, any, any>[],
const AllTraits extends Trait<any, any, any>[], const AllTraits extends Trait<any, any, any, any>[],
> { > {
constructor( constructor(
readonly superclass: Superclass, readonly superclass: Superclass,
@@ -52,17 +52,20 @@ export class TraitExpression<
subtrait< subtrait<
This extends TraitExpression<typeof TraitExpression.NullSuperclass, any, any>, This extends TraitExpression<typeof TraitExpression.NullSuperclass, any, any>,
SubtraitAbstract extends Implements<This>, SubtraitAbstract extends Implements<This>,
SubtraitStaticAbstract extends StaticImplements<This>,
SubtraitImplClassWithAbstract extends Class<SubtraitAbstract, []> & { _tag: TraitApplierSuperTag }, SubtraitImplClassWithAbstract extends Class<SubtraitAbstract, []> & { _tag: TraitApplierSuperTag },
>( >(
this: This, this: This,
abstract: (expression: This) => Opaque<SubtraitAbstract, AbstractTag>, abstract: (expression: This) => Opaque<SubtraitAbstract, AbstractTag>,
staticAbstract: (expression: This) => Opaque<SubtraitStaticAbstract, AbstractTag>,
apply: (Super: AbstractClass<SubtraitAbstract> & { _tag: TraitApplierSuperTag }) => SubtraitImplClassWithAbstract, apply: (Super: AbstractClass<SubtraitAbstract> & { _tag: TraitApplierSuperTag }) => SubtraitImplClassWithAbstract,
) { ) {
return new Trait( return new Trait(
this, this,
// {} as RemoveSupertraitsAbstractFromAbstract<SubtraitAbstract, Implements<typeof this>>, // {} as RemoveSupertraitsAbstractFromAbstract<SubtraitAbstract, Implements<typeof this>>,
{} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements<typeof this> from this. {} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements<typeof this> from this.
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<SubtraitImplClassWithAbstract, SubtraitAbstract>, {} as SubtraitStaticAbstract,
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<SubtraitImplClassWithAbstract, SubtraitAbstract, SubtraitStaticAbstract>,
) )
} }
} }
@@ -111,3 +114,12 @@ export type Implements<Exp extends TraitExpression<any, any, any>> = (
SimplifyFn, SimplifyFn,
]> ]>
) )
export type StaticImplements<Exp extends TraitExpression<any, any, any>> = (
Pipe<Exp, [
TraitExpression.AllTraitsFn,
Tuples.Map<Trait.OwnStaticAbstractFn>,
ExtendFn,
SimplifyFn,
]>
)

View File

@@ -5,7 +5,7 @@ import { TraitExpression, emptyTraitExpression } from "./TraitExpression"
import { ExtendableFn, StaticMembersFn } from "./util" import { ExtendableFn, StaticMembersFn } from "./util"
type SpreadSupertraits<Traits extends Trait<any, any, any>[]> = ( type SpreadSupertraits<Traits extends Trait<any, any, any, any>[]> = (
Call< Call<
Tuples.FlatMap<PrependTraitSupertraitsFn>, Tuples.FlatMap<PrependTraitSupertraitsFn>,
Traits Traits
@@ -18,7 +18,7 @@ interface PrependTraitSupertraitsFn extends Fn {
type AbstractMembersExtendable< type AbstractMembersExtendable<
Superclass extends AbstractClass<{}>, Superclass extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[], Traits extends Trait<any, any, any, any>[],
> = ( > = (
Pipe<Traits, [ Pipe<Traits, [
Tuples.Map<Trait.OwnAbstractFn>, Tuples.Map<Trait.OwnAbstractFn>,
@@ -28,7 +28,7 @@ type AbstractMembersExtendable<
type ImplInstanceExtendable< type ImplInstanceExtendable<
Superclass extends AbstractClass<{}>, Superclass extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[], Traits extends Trait<any, any, any, any>[],
> = ( > = (
Pipe<Traits, [ Pipe<Traits, [
Tuples.Map<Trait.OwnImplInstanceFn>, Tuples.Map<Trait.OwnImplInstanceFn>,
@@ -38,7 +38,7 @@ type ImplInstanceExtendable<
type ImplStaticMembersExtendable< type ImplStaticMembersExtendable<
Superclass extends AbstractClass<{}>, Superclass extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[], Traits extends Trait<any, any, any, any>[],
> = ( > = (
Pipe<Traits, [ Pipe<Traits, [
Tuples.Map<Trait.OwnImplClassFn>, Tuples.Map<Trait.OwnImplClassFn>,
@@ -50,8 +50,8 @@ type ImplStaticMembersExtendable<
type BuildTraitExpression< type BuildTraitExpression<
Superclass extends AbstractClass<{}>, Superclass extends AbstractClass<{}>,
OwnTraits extends Trait<any, any, any>[], OwnTraits extends Trait<any, any, any, any>[],
AllTraits extends Trait<any, any, any>[], AllTraits extends Trait<any, any, any, any>[],
> = ( > = (
AbstractMembersExtendable<Superclass, AllTraits> extends false AbstractMembersExtendable<Superclass, AllTraits> extends false
? "Type conflict between the traits abstract members and/or the superclass instance." ? "Type conflict between the traits abstract members and/or the superclass instance."
@@ -65,8 +65,8 @@ type BuildTraitExpression<
class TraitExpressionBuilder< class TraitExpressionBuilder<
Superclass extends AbstractClass<{}>, Superclass extends AbstractClass<{}>,
const OwnTraits extends Trait<any, any, any>[], const OwnTraits extends Trait<any, any, any, any>[],
const AllTraits extends Trait<any, any, any>[], const AllTraits extends Trait<any, any, any, any>[],
> { > {
constructor(private expression: TraitExpression<Superclass, OwnTraits, AllTraits>) {} constructor(private expression: TraitExpression<Superclass, OwnTraits, AllTraits>) {}
@@ -85,7 +85,7 @@ class TraitExpressionBuilder<
} }
expresses< expresses<
const Traits extends Trait<any, any, any>[] const Traits extends Trait<any, any, any, any>[]
>( >(
...traits: Traits ...traits: Traits
): TraitExpressionBuilder< ): TraitExpressionBuilder<
@@ -104,7 +104,8 @@ class TraitExpressionBuilder<
private spreadSupertraits< private spreadSupertraits<
const Traits extends Trait< const Traits extends Trait<
TraitExpression<any, any, Trait<any, any, any>[]>, TraitExpression<any, any, Trait<any, any, any, any>[]>,
any,
any, any,
any any
>[] >[]

View File

@@ -1,10 +1,11 @@
import { Trait, trait } from "./Trait" import { Trait, trait } from "./Trait"
import { Implements } from "./TraitExpression" import { Implements, StaticImplements } from "./TraitExpression"
import { expression } from "./TraitExpressionBuilder" import { expression } from "./TraitExpressionBuilder"
import { abstract } from "./abstract" import { abstract } from "./abstract"
const PrintsHelloOnNew = trait( const PrintsHelloOnNew = trait(
abstract(),
abstract(), abstract(),
Super => class PrintsHelloOnNew extends Super { Super => class PrintsHelloOnNew extends Super {
static readonly isPrintsHelloOnNew = true static readonly isPrintsHelloOnNew = true
@@ -19,6 +20,7 @@ type PrintsHelloOnNewClass = Trait.Class<typeof PrintsHelloOnNew>
const Identifiable = <ID>() => trait( const Identifiable = <ID>() => trait(
abstract<{ readonly id: ID }>(), abstract<{ readonly id: ID }>(),
abstract(),
Super => class Identifiable extends Super { Super => class Identifiable extends Super {
equals(el: Identifiable) { equals(el: Identifiable) {
return this.id === el.id return this.id === el.id
@@ -35,6 +37,7 @@ const StatefulSubscription = trait(
{ _tag: "expired", expiredSince: Date } { _tag: "expired", expiredSince: Date }
) )
}>(), }>(),
abstract(),
Super => class StatefulSubscription extends Super {}, Super => class StatefulSubscription extends Super {},
) )
@@ -53,6 +56,8 @@ const ActiveStatefulSubscription = expression
return abstract<IActiveStatefulSubscription>() return abstract<IActiveStatefulSubscription>()
}, },
exp => abstract<StaticImplements<typeof exp>>(),
Super => class ActiveStatefulSubscription extends Super {}, Super => class ActiveStatefulSubscription extends Super {},
) )
@@ -86,7 +91,9 @@ class User extends exp.extends implements Implements<typeof exp> {
console.log(new User()) console.log(new User())
declare function StaticImplements(target: { issou: string }, context: any): typeof target declare function StaticImplements(target: { issou: string }, context: any): void
@StaticImplements @StaticImplements
class Gneugneu {} class Gneugneu {
// static issou: string = "juif"
}