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 { expresses, extendsAndExpresses, trait } from "."
|
||||
import { ClassesInstances, MergeInheritanceTree } from "./util"
|
||||
import { trait } from "."
|
||||
|
||||
|
||||
const Identifiable = <ID>() =>
|
||||
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 {
|
||||
}
|
||||
const PrintsHelloOnNew = trait()
|
||||
|
||||
26
src/trait.ts
26
src/trait.ts
@@ -2,6 +2,17 @@ import { AbstractClass, Class, Opaque } from "type-fest"
|
||||
import { StaticMembers } from "./util"
|
||||
|
||||
|
||||
type AddAbstractMembersToImpl<
|
||||
Impl extends Class<object, []>,
|
||||
AbstractMembers extends object,
|
||||
> = (
|
||||
Class<
|
||||
InstanceType<Impl> & AbstractMembers,
|
||||
ConstructorParameters<Impl>
|
||||
> &
|
||||
StaticMembers<Impl>
|
||||
)
|
||||
|
||||
type RemoveAbstractMembersFromImpl<
|
||||
ImplWithAbstractMembers extends Class<AbstractMembers, []>,
|
||||
AbstractMembers extends object,
|
||||
@@ -18,11 +29,16 @@ export type TraitTag = "@thilawyn/traitify-ts/Trait"
|
||||
|
||||
export type Trait<
|
||||
AbstractMembers extends object,
|
||||
Impl extends Class<any, []>,
|
||||
Impl extends Class<object, []>,
|
||||
> = (
|
||||
Opaque<{
|
||||
readonly AbstractMembers: AbstractMembers
|
||||
readonly Impl: Impl
|
||||
readonly apply: TraitApplier<
|
||||
AbstractMembers,
|
||||
AddAbstractMembersToImpl<
|
||||
Impl,
|
||||
AbstractMembers
|
||||
>
|
||||
>
|
||||
}, TraitTag>
|
||||
)
|
||||
|
||||
@@ -43,7 +59,7 @@ export function trait<
|
||||
AbstractMembers extends object = {}
|
||||
>(): (
|
||||
<ImplWithAbstractMembers extends Class<AbstractMembers, []>>(
|
||||
applier: TraitApplier<AbstractMembers, ImplWithAbstractMembers>
|
||||
apply: TraitApplier<AbstractMembers, ImplWithAbstractMembers>
|
||||
) => Trait<
|
||||
AbstractMembers,
|
||||
RemoveAbstractMembersFromImpl<
|
||||
@@ -52,5 +68,5 @@ export function trait<
|
||||
>
|
||||
>
|
||||
) {
|
||||
return (applier) => applier()
|
||||
return apply => ({ apply }) as any
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user