Trait work
This commit is contained in:
131
src/tests.ts
131
src/tests.ts
@@ -1,131 +1,4 @@
|
|||||||
import { AbstractClass } from "type-fest"
|
import { trait } from "."
|
||||||
import { expresses, extendsAndExpresses, trait } from "."
|
|
||||||
import { ClassesInstances, MergeInheritanceTree } from "./util"
|
|
||||||
|
|
||||||
|
|
||||||
const Identifiable = <ID>() =>
|
const PrintsHelloOnNew = trait()
|
||||||
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 = <ID>(defaultID: ID) =>
|
|
||||||
trait(Super => {
|
|
||||||
abstract class ImplementsIdentifiable extends extendsAndExpresses(
|
|
||||||
Super,
|
|
||||||
Identifiable<ID>(),
|
|
||||||
) {
|
|
||||||
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[] = []
|
|
||||||
|
|
||||||
constructor(...args: any[]) {
|
|
||||||
super(...args)
|
|
||||||
console.log("Permissible constructor")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Permissible
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const UserProto = expresses(
|
|
||||||
// Identifiable<bigint>(),
|
|
||||||
ImplementsIdentifiable(0n),
|
|
||||||
Permissible,
|
|
||||||
)
|
|
||||||
|
|
||||||
class User extends UserProto {
|
|
||||||
constructor(id: bigint) {
|
|
||||||
super()
|
|
||||||
this.id = 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: (
|
|
||||||
{ _tag: "awaitingPayment" } |
|
|
||||||
{ _tag: "active", activeSince: Date, expiresAt?: Date } |
|
|
||||||
{ _tag: "expired", expiredSince: Date }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Test1
|
|
||||||
})
|
|
||||||
|
|
||||||
const Test2 = trait(Super => {
|
|
||||||
abstract class Test2 extends Super {
|
|
||||||
declare readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date }
|
|
||||||
}
|
|
||||||
|
|
||||||
return Test2
|
|
||||||
})
|
|
||||||
|
|
||||||
const Test3 = trait(Super => {
|
|
||||||
abstract class Test3 extends Super {
|
|
||||||
declare static testValue: { _tag: "type2", value: number }
|
|
||||||
declare lol: 10n
|
|
||||||
}
|
|
||||||
|
|
||||||
return Test3
|
|
||||||
})
|
|
||||||
|
|
||||||
const TestObjectProto = expresses(Test1, Test2, Test3)
|
|
||||||
TestObjectProto.testValue
|
|
||||||
|
|
||||||
|
|
||||||
interface Gneugneu {
|
|
||||||
ahi: string
|
|
||||||
get adolf(): string
|
|
||||||
}
|
|
||||||
|
|
||||||
class GneugneuImpl implements Gneugneu {
|
|
||||||
ahi: string = ""
|
|
||||||
get adolf(): string {
|
|
||||||
throw new Error("Method not implemented.")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Issou extends GneugneuImpl implements Gneugneu {
|
|
||||||
}
|
|
||||||
|
|||||||
26
src/trait.ts
26
src/trait.ts
@@ -2,6 +2,17 @@ import { AbstractClass, Class, Opaque } from "type-fest"
|
|||||||
import { StaticMembers } from "./util"
|
import { StaticMembers } from "./util"
|
||||||
|
|
||||||
|
|
||||||
|
type AddAbstractMembersToImpl<
|
||||||
|
Impl extends Class<object, []>,
|
||||||
|
AbstractMembers extends object,
|
||||||
|
> = (
|
||||||
|
Class<
|
||||||
|
InstanceType<Impl> & AbstractMembers,
|
||||||
|
ConstructorParameters<Impl>
|
||||||
|
> &
|
||||||
|
StaticMembers<Impl>
|
||||||
|
)
|
||||||
|
|
||||||
type RemoveAbstractMembersFromImpl<
|
type RemoveAbstractMembersFromImpl<
|
||||||
ImplWithAbstractMembers extends Class<AbstractMembers, []>,
|
ImplWithAbstractMembers extends Class<AbstractMembers, []>,
|
||||||
AbstractMembers extends object,
|
AbstractMembers extends object,
|
||||||
@@ -18,11 +29,16 @@ export type TraitTag = "@thilawyn/traitify-ts/Trait"
|
|||||||
|
|
||||||
export type Trait<
|
export type Trait<
|
||||||
AbstractMembers extends object,
|
AbstractMembers extends object,
|
||||||
Impl extends Class<any, []>,
|
Impl extends Class<object, []>,
|
||||||
> = (
|
> = (
|
||||||
Opaque<{
|
Opaque<{
|
||||||
readonly AbstractMembers: AbstractMembers
|
readonly apply: TraitApplier<
|
||||||
readonly Impl: Impl
|
AbstractMembers,
|
||||||
|
AddAbstractMembersToImpl<
|
||||||
|
Impl,
|
||||||
|
AbstractMembers
|
||||||
|
>
|
||||||
|
>
|
||||||
}, TraitTag>
|
}, TraitTag>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,7 +59,7 @@ export function trait<
|
|||||||
AbstractMembers extends object = {}
|
AbstractMembers extends object = {}
|
||||||
>(): (
|
>(): (
|
||||||
<ImplWithAbstractMembers extends Class<AbstractMembers, []>>(
|
<ImplWithAbstractMembers extends Class<AbstractMembers, []>>(
|
||||||
applier: TraitApplier<AbstractMembers, ImplWithAbstractMembers>
|
apply: TraitApplier<AbstractMembers, ImplWithAbstractMembers>
|
||||||
) => Trait<
|
) => Trait<
|
||||||
AbstractMembers,
|
AbstractMembers,
|
||||||
RemoveAbstractMembersFromImpl<
|
RemoveAbstractMembersFromImpl<
|
||||||
@@ -52,5 +68,5 @@ export function trait<
|
|||||||
>
|
>
|
||||||
>
|
>
|
||||||
) {
|
) {
|
||||||
return (applier) => applier()
|
return apply => ({ apply }) as any
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user