Trait work

This commit is contained in:
Julien Valverdé
2024-01-28 20:16:10 +01:00
parent f5ab00c34a
commit e46f78d93e
2 changed files with 23 additions and 134 deletions

View File

@@ -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()

View File

@@ -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
}