Implementation using mixins
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Julien Valverdé
2023-12-28 04:03:08 +01:00
parent 77d7dbe837
commit 3a155d5ef9
2 changed files with 109 additions and 0 deletions

45
src/tests-inheritance.ts Normal file
View File

@@ -0,0 +1,45 @@
import { extendsAndExpresses, trait } from "./trait-inheritance"
const Identified = <ID>() =>
trait(Parent => {
abstract class Identified<ID> extends Parent {
abstract id: ID
equals(el: Identified<ID>) {
return this.id === el.id
}
}
return Identified<ID>
})
const Permissible = trait(Parent => {
abstract class Permissible extends Parent {
static readonly defaultPermissions: string[] = []
permissions: string[] = []
constructor() {
super()
console.log("Permissible constructor")
}
}
return Permissible
})
const UserProto = extendsAndExpresses(class {}, [
Identified<bigint>(),
Permissible,
] as const)
class User extends UserProto {
constructor(readonly id: bigint) {
super()
}
}
const user1 = new User(1n)
user1.equals(user1)

64
src/trait-inheritance.ts Normal file
View File

@@ -0,0 +1,64 @@
import { AbstractClass, Opaque, UnionToIntersection } from "type-fest"
/**
* Represents the static members of a class.
*
* @template C - The type of the class for which static members are extracted.
* @typeparam The static members of the class.
*/
export type StaticMembers<C> = Pick<C, keyof C>
export type Trait<C extends AbstractClass<any, any>> =
Opaque<(Parent: AbstractClass<any, any[]>) => C, "Trait">
export type GetTraitC<T> =
T extends Trait<infer C>
? C
: never
export function trait<
C extends AbstractClass<any, any[]>
>(
trait: (Parent: AbstractClass<any, any[]>) => C
) {
return trait as Trait<C>
}
export function extendsAndExpresses<
C extends AbstractClass<any, any>,
Traits extends readonly Trait<any>[],
>(
extend: C,
traits: Traits,
) {
return extend as unknown as (
AbstractClass<
InstanceType<C> &
UnionToIntersection<
InstanceType<
GetTraitC<
Traits[number]
>
>
>,
ConstructorParameters<C>
> &
StaticMembers<C> &
StaticMembers<
UnionToIntersection<
GetTraitC<
Traits[number]
>
>
>
)
}