85 lines
2.3 KiB
TypeScript
85 lines
2.3 KiB
TypeScript
import { AbstractClass, Opaque } from "type-fest"
|
|
import { Trait, TraitApplierSuperTag } from "."
|
|
import { ClassesInstances, ClassesStaticMembers, MergeInheritanceTree, MergeInheritanceTreeWithoutOverriding, StaticMembers, TraitsClasses } from "./util"
|
|
|
|
|
|
/**
|
|
* Extends a class with the given traits and expresses their combined functionality.
|
|
* @template C - The abstract class type.
|
|
* @template Traits - An array of traits.
|
|
* @param extend - The class to extend.
|
|
* @param traits - An array of traits to apply.
|
|
* @returns A new class type expressing the combined functionality of the base class and traits.
|
|
* @example
|
|
* Extends a superclass and applies traits:
|
|
* ```ts
|
|
* class User extends extendsAndExpresses(Entity,
|
|
* Identifiable<bigint>(),
|
|
* Permissible,
|
|
* ) {
|
|
* readonly id: bigint
|
|
*
|
|
* constructor(id: bigint) {
|
|
* super()
|
|
* this.id = id
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export function extendsAndExpresses<
|
|
C extends AbstractClass<any>,
|
|
Traits extends readonly Trait<any>[],
|
|
>(
|
|
extend: C,
|
|
...traits: Traits
|
|
) {
|
|
return traits.reduce(
|
|
(previous, trait) => trait(previous),
|
|
extend as Opaque<C, TraitApplierSuperTag>,
|
|
) as unknown as (
|
|
AbstractClass<
|
|
MergeInheritanceTreeWithoutOverriding<[
|
|
InstanceType<C>,
|
|
...ClassesInstances<
|
|
TraitsClasses<Traits>
|
|
>,
|
|
]>,
|
|
|
|
ConstructorParameters<C>
|
|
> &
|
|
|
|
MergeInheritanceTree<[
|
|
StaticMembers<C>,
|
|
...ClassesStaticMembers<
|
|
TraitsClasses<Traits>
|
|
>,
|
|
]>
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Expresses the combined functionality of multiple traits.
|
|
* @template Traits - An array of trait.
|
|
* @param traits - An array of trait to apply.
|
|
* @returns A new class type expressing the combined functionality of the traits.
|
|
* @example
|
|
* Applies traits to a class:
|
|
* ```ts
|
|
* class User extends expresses(Identifiable<bigint>(), Permissible) {
|
|
* readonly id: bigint
|
|
*
|
|
* constructor(id: bigint) {
|
|
* super()
|
|
* this.id = id
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export function expresses<
|
|
Traits extends readonly Trait<any>[],
|
|
>(
|
|
...traits: Traits
|
|
) {
|
|
return extendsAndExpresses(Object, ...traits)
|
|
}
|