This commit is contained in:
24
src/tests.ts
24
src/tests.ts
@@ -27,6 +27,10 @@ abstract class Identified<ID> {
|
|||||||
equals(el: Identified<ID>) {
|
equals(el: Identified<ID>) {
|
||||||
return this.id === el.id
|
return this.id === el.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initializer() {
|
||||||
|
// console.log("Identified initializer")
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImplementsIdentifiable<ID> extends Identified<ID> {
|
class ImplementsIdentifiable<ID> extends Identified<ID> {
|
||||||
@@ -36,7 +40,13 @@ class ImplementsIdentifiable<ID> extends Identified<ID> {
|
|||||||
|
|
||||||
abstract class Permissible {
|
abstract class Permissible {
|
||||||
static readonly defaultPermissions: string[] = []
|
static readonly defaultPermissions: string[] = []
|
||||||
permissions: string[] = []
|
// permissions: string[] = []
|
||||||
|
permissions!: string[]
|
||||||
|
|
||||||
|
initializer() {
|
||||||
|
console.log("Permissible initializer")
|
||||||
|
this.permissions = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -55,11 +65,11 @@ class User extends expresses(
|
|||||||
|
|
||||||
console.log(new User(BigInt(1)))
|
console.log(new User(BigInt(1)))
|
||||||
|
|
||||||
// console.log(Permissible.constructor())
|
console.log(Permissible.constructor())
|
||||||
// console.log(Object.getOwnPropertyNames(User.prototype))
|
console.log(Object.getOwnPropertyNames(User.prototype))
|
||||||
|
|
||||||
// const user1 = new User(BigInt(1))
|
const user1 = new User(BigInt(1))
|
||||||
// const user2 = new User(BigInt(2))
|
const user2 = new User(BigInt(2))
|
||||||
|
|
||||||
// console.log(user1.equals(user2))
|
console.log(user1.equals(user2))
|
||||||
// console.log(user1.permissions)
|
console.log(user1.permissions)
|
||||||
|
|||||||
153
src/trait.ts
153
src/trait.ts
@@ -1,72 +1,85 @@
|
|||||||
import { AbstractClass, Class, UnionToIntersection } from "type-fest"
|
import { AbstractClass, Class, UnionToIntersection } from "type-fest"
|
||||||
import { StaticMembers, copyProperties, flattenClass, getInheritanceHierarchy } from "./util/class"
|
import { StaticMembers, copyProperties, getInheritanceHierarchy } from "./util/class"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a trait that can be used to define common behavior
|
||||||
|
* for classes and abstract classes.
|
||||||
|
* @typeParam T - The type of the trait.
|
||||||
|
*/
|
||||||
export type Trait<T> =
|
export type Trait<T> =
|
||||||
AbstractClass<T, []>
|
AbstractClass<T, []>
|
||||||
|
|
||||||
|
|
||||||
// export function applyTrait<
|
/**
|
||||||
// C extends Class<any, any> | AbstractClass<any, any>,
|
* Creates a link class that expresses the given traits.
|
||||||
// TraitC extends Trait<any>,
|
* @param traits - An array of traits to be expressed by the link class.
|
||||||
// >(
|
* @returns A dynamically created class that expresses the given traits.
|
||||||
// class_: C,
|
* @typeParam Traits - An array of traits that the link class expresses.
|
||||||
// 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<
|
export function expresses<
|
||||||
Traits extends readonly Trait<any>[]
|
Traits extends readonly Trait<any>[]
|
||||||
>(
|
>(
|
||||||
...traits: Traits
|
...traits: Traits
|
||||||
) {
|
) {
|
||||||
const class_ = class {}
|
return makeLinkClass(traits)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a link class that extends a base class and expresses the given traits.
|
||||||
|
* @param extend - The base class or abstract class to extend.
|
||||||
|
* @param traits - An array of traits to be expressed by the link class.
|
||||||
|
* @returns A dynamically created class that extends the given base class and expresses the given traits.
|
||||||
|
* @typeParam C - The type of the base class to extend.
|
||||||
|
* @typeParam Traits - An array of traits that the link class expresses.
|
||||||
|
*/
|
||||||
|
export function extendsAndExpresses<
|
||||||
|
C extends Class<any, any>
|
||||||
|
| AbstractClass<any, any>,
|
||||||
|
Traits extends readonly Trait<any>[],
|
||||||
|
>(
|
||||||
|
extend: C,
|
||||||
|
...traits: Traits
|
||||||
|
) {
|
||||||
|
return makeLinkClass(traits, extend)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a link class that expresses the given traits and optionally extends a base class.
|
||||||
|
* @param traits - An array of traits to be expressed by the link class.
|
||||||
|
* @param extend - The base class or abstract class to extend (optional).
|
||||||
|
* @returns A dynamically created class that expresses the given traits and extends the base class.
|
||||||
|
* @typeParam Traits - An array of traits that the link class expresses.
|
||||||
|
* @typeParam C - The type of the base class to extend (optional).
|
||||||
|
*/
|
||||||
|
export function makeLinkClass<
|
||||||
|
Traits extends readonly Trait<any>[],
|
||||||
|
C extends Class<any, any>
|
||||||
|
| AbstractClass<any, any>
|
||||||
|
| undefined = undefined,
|
||||||
|
>(
|
||||||
|
traits: Traits,
|
||||||
|
extend?: C,
|
||||||
|
) {
|
||||||
|
const class_ = extend
|
||||||
|
? class extends extend {
|
||||||
|
constructor(...args: any[]) {
|
||||||
|
super(...args)
|
||||||
|
|
||||||
|
traits.forEach(trait => {
|
||||||
|
trait.prototype.initializer?.call(this)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: class {
|
||||||
|
constructor() {
|
||||||
|
traits.forEach(trait => {
|
||||||
|
trait.prototype.initializer?.call(this)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
traits.forEach(trait => {
|
traits.forEach(trait => {
|
||||||
getInheritanceHierarchy(trait).forEach(current => {
|
getInheritanceHierarchy(trait).forEach(current => {
|
||||||
@@ -80,13 +93,29 @@ export function expresses<
|
|||||||
})
|
})
|
||||||
|
|
||||||
return class_ as unknown as (
|
return class_ as unknown as (
|
||||||
Trait<
|
(C extends Class<any, any> | AbstractClass<any, any>
|
||||||
UnionToIntersection<
|
? (
|
||||||
InstanceType<
|
AbstractClass<
|
||||||
Traits[number]
|
InstanceType<C> &
|
||||||
|
UnionToIntersection<
|
||||||
|
InstanceType<
|
||||||
|
Traits[number]
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
|
||||||
|
ConstructorParameters<C>
|
||||||
|
> &
|
||||||
|
|
||||||
|
StaticMembers<C>
|
||||||
|
)
|
||||||
|
: Trait<
|
||||||
|
UnionToIntersection<
|
||||||
|
InstanceType<
|
||||||
|
Traits[number]
|
||||||
|
>
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> &
|
) &
|
||||||
|
|
||||||
StaticMembers<
|
StaticMembers<
|
||||||
UnionToIntersection<
|
UnionToIntersection<
|
||||||
|
|||||||
Reference in New Issue
Block a user