This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
import { Call, Pipe, Tuples } from "hotscript"
|
import { Call, Fn, Pipe, Tuples } from "hotscript"
|
||||||
import { AbstractClass, Class, Opaque } from "type-fest"
|
import { AbstractClass, Class, Opaque } from "type-fest"
|
||||||
import { AbstractTag, Trait, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn } from "."
|
import { AbstractTag, Trait, TraitAbstractFn, TraitApplierSuperTag, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn } from "."
|
||||||
import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util"
|
import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util"
|
||||||
|
|
||||||
|
|
||||||
|
export class TraitExpressionNullSuperclass {}
|
||||||
|
|
||||||
export class TraitExpression<
|
export class TraitExpression<
|
||||||
Super extends AbstractClass<{}>,
|
Super extends AbstractClass<{}>,
|
||||||
Traits extends Trait<any, any, any>[],
|
Traits extends Trait<any, any, any>[],
|
||||||
@@ -58,6 +60,46 @@ export class TraitExpression<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const emptyTraitExpression = new TraitExpression(TraitExpressionNullSuperclass, [] as const)
|
||||||
|
|
||||||
|
interface PrependTraitSupertraitsFn extends Fn {
|
||||||
|
return: [
|
||||||
|
...Call<TraitSupertraitsFn, this["arg0"]>,
|
||||||
|
this["arg0"],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
export interface TraitExpressionTraitsFn extends Fn {
|
||||||
|
return: this["arg0"] extends TraitExpression<any, infer Traits>
|
||||||
|
? Call<Tuples.FlatMap<PrependTraitSupertraitsFn>, Traits>
|
||||||
|
: never
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TraitExpressionAbstractFn extends Fn {
|
||||||
|
return: this["arg0"] extends TraitExpression<any, infer Traits>
|
||||||
|
? Pipe<Traits, [
|
||||||
|
TraitAbstractFn,
|
||||||
|
ExtendFn,
|
||||||
|
]>
|
||||||
|
: never
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TraitExpressionInstanceFn extends Fn {
|
||||||
|
return: this["arg0"] extends TraitExpression<infer Super, infer Traits>
|
||||||
|
? Pipe<Traits, [
|
||||||
|
TraitAbstractFn,
|
||||||
|
ExtendFn,
|
||||||
|
]>
|
||||||
|
: never
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TraitExpressionStaticFn extends Fn {
|
||||||
|
return: this["arg0"] extends TraitExpression<infer Super, infer Traits>
|
||||||
|
? Pipe<Traits, [
|
||||||
|
TraitAbstractFn,
|
||||||
|
ExtendFn,
|
||||||
|
]>
|
||||||
|
: never
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type Implements<Exp extends TraitExpression<any, any>> = (
|
export type Implements<Exp extends TraitExpression<any, any>> = (
|
||||||
@@ -158,8 +200,4 @@ type GetTraitExpression<
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
export class NullTraitExpressionSuperclass {}
|
export const expression = new TraitExpressionBuilder(emptyTraitExpression)
|
||||||
|
|
||||||
export const expression = new TraitExpressionBuilder(
|
|
||||||
new TraitExpression(NullTraitExpressionSuperclass, [] as const)
|
|
||||||
)
|
|
||||||
|
|||||||
16
src/tests.ts
16
src/tests.ts
@@ -1,4 +1,4 @@
|
|||||||
import { Implements, TraitAbstractMembers, abstract, expression, trait } from "."
|
import { Implements, abstract, expression, trait } from "."
|
||||||
|
|
||||||
|
|
||||||
const PrintsHelloOnNew = trait(
|
const PrintsHelloOnNew = trait(
|
||||||
@@ -32,14 +32,14 @@ const StatefulSubscription = trait(
|
|||||||
Super => class StatefulSubscription extends Super {},
|
Super => class StatefulSubscription extends Super {},
|
||||||
)
|
)
|
||||||
|
|
||||||
interface ActiveStatefulSubscriptionAbstractMembers extends TraitAbstractMembers<typeof StatefulSubscription> {
|
// interface ActiveStatefulSubscriptionAbstractMembers extends TraitAbstractMembers<typeof StatefulSubscription> {
|
||||||
readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date }
|
// readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const ActiveStatefulSubscription = trait(
|
// const ActiveStatefulSubscription = trait(
|
||||||
abstract<ActiveStatefulSubscriptionAbstractMembers>(),
|
// abstract<ActiveStatefulSubscriptionAbstractMembers>(),
|
||||||
Super => class ActiveStatefulSubscription extends Super {},
|
// Super => class ActiveStatefulSubscription extends Super {},
|
||||||
)
|
// )
|
||||||
|
|
||||||
|
|
||||||
class TestSuperclass {
|
class TestSuperclass {
|
||||||
|
|||||||
26
src/trait.ts
26
src/trait.ts
@@ -1,7 +1,7 @@
|
|||||||
import { Call, Fn } from "hotscript"
|
import { Call, Fn } from "hotscript"
|
||||||
import { AbstractClass, Class, Opaque } from "type-fest"
|
import { AbstractClass, Class, Opaque } from "type-fest"
|
||||||
import { AbstractTag, NullTraitExpressionSuperclass, TraitExpression } from "."
|
import { AbstractTag, TraitExpression, TraitExpressionAbstractFn, TraitExpressionNullSuperclass, TraitExpressionTraitsFn, emptyTraitExpression } from "."
|
||||||
import { StaticMembers } from "./util"
|
import { ExtendFn, StaticMembers } from "./util"
|
||||||
|
|
||||||
|
|
||||||
type AddAbstractToImplClass<
|
type AddAbstractToImplClass<
|
||||||
@@ -28,7 +28,7 @@ type RemoveAbstractFromImplClass<
|
|||||||
|
|
||||||
|
|
||||||
export class Trait<
|
export class Trait<
|
||||||
Super extends TraitExpression<typeof NullTraitExpressionSuperclass, any>[],
|
Super extends TraitExpression<typeof TraitExpressionNullSuperclass, any>,
|
||||||
Abstract extends {},
|
Abstract extends {},
|
||||||
ImplClass extends Class<{}, []>,
|
ImplClass extends Class<{}, []>,
|
||||||
> {
|
> {
|
||||||
@@ -54,7 +54,7 @@ export interface TraitOwnImplClassFn extends Fn {
|
|||||||
export type TraitOwnImplClass<T> = Call<TraitOwnImplClassFn, T>
|
export type TraitOwnImplClass<T> = Call<TraitOwnImplClassFn, T>
|
||||||
|
|
||||||
export interface TraitOwnImplInstanceFn extends Fn {
|
export interface TraitOwnImplInstanceFn extends Fn {
|
||||||
return: this["arg0"] extends Trait<any, infer Abstract, infer ImplClass>
|
return: this["arg0"] extends Trait<any, any, infer ImplClass>
|
||||||
? InstanceType<ImplClass>
|
? InstanceType<ImplClass>
|
||||||
: never
|
: never
|
||||||
}
|
}
|
||||||
@@ -77,6 +77,22 @@ export interface TraitOwnInstanceFn extends Fn {
|
|||||||
export type TraitOwnInstance<T> = Call<TraitOwnInstanceFn, T>
|
export type TraitOwnInstance<T> = Call<TraitOwnInstanceFn, T>
|
||||||
|
|
||||||
|
|
||||||
|
export interface TraitSupertraitsFn extends Fn {
|
||||||
|
return: this["arg0"] extends Trait<infer Super, any, any>
|
||||||
|
? Call<TraitExpressionTraitsFn, Super>
|
||||||
|
: never
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TraitAbstractFn extends Fn {
|
||||||
|
return: this["arg0"] extends Trait<infer Super, infer Abstract, any>
|
||||||
|
? Call<ExtendFn, [
|
||||||
|
...Call<TraitExpressionAbstractFn, Super>,
|
||||||
|
Abstract,
|
||||||
|
]>
|
||||||
|
: never
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper"
|
export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper"
|
||||||
|
|
||||||
export function trait<
|
export function trait<
|
||||||
@@ -89,7 +105,7 @@ export function trait<
|
|||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
return new Trait(
|
return new Trait(
|
||||||
[] as const,
|
emptyTraitExpression,
|
||||||
abstract as Abstract,
|
abstract as Abstract,
|
||||||
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<ImplClassWithAbstract, Abstract>,
|
apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass<ImplClassWithAbstract, Abstract>,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user