98 lines
2.2 KiB
TypeScript
98 lines
2.2 KiB
TypeScript
import { AbstractClass, Class, UnionToIntersection } from "type-fest"
|
|
import { StaticMembers, copyProperties, flattenClass, getInheritanceHierarchy } from "./util/class"
|
|
|
|
|
|
export type Trait<T> =
|
|
AbstractClass<T, []>
|
|
|
|
|
|
// export function applyTrait<
|
|
// C extends Class<any, any> | AbstractClass<any, any>,
|
|
// TraitC extends Trait<any>,
|
|
// >(
|
|
// class_: C,
|
|
// trait: TraitC,
|
|
// ) {
|
|
// copyClassProperties(trait, class_)
|
|
|
|
// return class_ as (
|
|
// (C extends Class<any, any>
|
|
// ? Class<
|
|
// InstanceType<C> & InstanceType<TraitC>,
|
|
// ConstructorParameters<C>
|
|
// >
|
|
// : AbstractClass<
|
|
// InstanceType<C> & InstanceType<TraitC>,
|
|
// ConstructorParameters<C>
|
|
// >
|
|
// ) &
|
|
// StaticMembers<C> &
|
|
// StaticMembers<TraitC>
|
|
// )
|
|
// }
|
|
|
|
|
|
export const extendAndApplyTraits = <
|
|
C extends Class<any, any> | AbstractClass<any, any>,
|
|
Traits extends readonly Trait<any>[],
|
|
>(
|
|
classToExtend: C,
|
|
traits: Traits,
|
|
) =>
|
|
traits.reduce((class_, trait) => {
|
|
copyProperties(flattenClass(trait), class_)
|
|
return class_
|
|
}, class extends classToExtend {}) as (
|
|
AbstractClass<
|
|
InstanceType<C> &
|
|
UnionToIntersection<
|
|
InstanceType<Traits[number]>
|
|
>,
|
|
|
|
ConstructorParameters<C>
|
|
> &
|
|
|
|
StaticMembers<
|
|
C &
|
|
UnionToIntersection<
|
|
Traits[number]
|
|
>
|
|
>
|
|
)
|
|
|
|
|
|
export function expresses<
|
|
Traits extends readonly Trait<any>[]
|
|
>(
|
|
...traits: Traits
|
|
) {
|
|
const class_ = class {}
|
|
|
|
traits.forEach(trait => {
|
|
getInheritanceHierarchy(trait).forEach(current => {
|
|
copyProperties(
|
|
current,
|
|
class_,
|
|
["name", "length"],
|
|
["constructor"],
|
|
)
|
|
})
|
|
})
|
|
|
|
return class_ as unknown as (
|
|
Trait<
|
|
UnionToIntersection<
|
|
InstanceType<
|
|
Traits[number]
|
|
>
|
|
>
|
|
> &
|
|
|
|
StaticMembers<
|
|
UnionToIntersection<
|
|
Traits[number]
|
|
>
|
|
>
|
|
)
|
|
}
|