0.1.2 #9

Merged
Thilawyn merged 8 commits from next into master 2024-01-27 23:40:19 +01:00
4 changed files with 120 additions and 41 deletions
Showing only changes of commit 92645bfd6b - Show all commits

View File

@@ -1,5 +1,6 @@
import { AbstractClass } from "type-fest" import { AbstractClass, UnionToIntersection } from "type-fest"
import { expresses, extendsAndExpresses, trait } from "." import { expresses, extendsAndExpresses, trait } from "."
import { ClassesInstances, ClassesInstancesIntersection, ClassesStaticMembers, MergeInheritanceTree, MergeInheritanceTreeWithoutOverriding } from "./util"
const Identifiable = <ID>() => const Identifiable = <ID>() =>
@@ -92,46 +93,16 @@ class Test3 {
} }
type CommonKeys<A, B> = Extract<keyof A, keyof B>
type Extend<T extends readonly any[]> = (
T extends [infer Super, infer Self, ...infer Rest]
? Pick<Self, CommonKeys<Self, Super>> extends Pick<Super, CommonKeys<Self, Super>>
? Extend<[
Omit<Super, CommonKeys<Self, Super>> & Self,
...Rest,
]>
: never
: T extends [infer Self]
? Self
: "Empty array"
)
type ClassesInstances<Classes extends readonly any[]> = (
Classes extends [infer Class, ...infer Rest]
? Class extends AbstractClass<any>
? [InstanceType<Class>, ...ClassesInstances<Rest>]
: never
: []
)
type StaticMembers<Class extends AbstractClass<any>> = (
Omit<Class, "prototype">
)
type ClassesStaticMembers<Classes extends readonly any[]> = (
Classes extends [infer Class, ...infer Rest]
? Class extends AbstractClass<any>
? [StaticMembers<Class>, ...ClassesStaticMembers<Rest>]
: never
: []
)
type ExtendClasses<Classes extends readonly AbstractClass<any>[]> = ( type ExtendClasses<Classes extends readonly AbstractClass<any>[]> = (
AbstractClass< AbstractClass<
Extend<ClassesInstances<Classes>> // Extend<ClassesInstances<Classes>>
MergeInheritanceTreeWithoutOverriding<
ClassesInstances<Classes>
>
> & > &
Extend<ClassesStaticMembers<Classes>> MergeInheritanceTree<
ClassesStaticMembers<Classes>
>
) )
@@ -140,13 +111,13 @@ type MixedTestProto = ExtendClasses<[
typeof Test2, typeof Test2,
typeof Test3, typeof Test3,
]> ]>
declare const MixedTestProto: MixedTestProto declare const MixedTestProto: MixedTestProto
class MixedTest extends MixedTestProto {} class MixedTest extends MixedTestProto {
}
MixedTest.prototype MixedTest.prototype
new MixedTest().name new MixedTest().status.expiresAt
// type MixedTestTraitsProto = Class< // type MixedTestTraitsProto = Class<
// Extend2<TestTrait2, TestTrait1>, // Extend2<TestTrait2, TestTrait1>,

66
src/util/class.ts Normal file
View File

@@ -0,0 +1,66 @@
import { AbstractClass } from "type-fest"
/**
* Represents an array of instances corresponding to the provided classes.
* @template Classes - An array of classes extending AbstractClass.
*/
export type ClassesInstances<Classes extends readonly AbstractClass<any>[]> = (
Classes extends [infer Class, ...infer Rest]
? Class extends AbstractClass<any>
? Rest extends AbstractClass<any>[]
? [InstanceType<Class>, ...ClassesInstances<Rest>]
: never
: never
: []
)
/**
* Represents an intersection of instances of the provided classes.
* @template Classes - An array of classes extending AbstractClass.
*/
export type ClassesInstancesIntersection<Classes extends readonly AbstractClass<any>[]> = (
Classes extends [infer Class, ...infer Rest]
? Class extends AbstractClass<any>
? Rest extends AbstractClass<any>[]
? InstanceType<Class> & ClassesInstancesIntersection<Rest>
: never
: never
: {}
)
/**
* Represents the static members of a class.
* @template Class - A class extending AbstractClass.
*/
export type StaticMembers<Class extends AbstractClass<any>> = (
Omit<Class, "prototype">
)
/**
* Represents an array of static members corresponding to the provided classes.
* @template Classes - An array of classes extending AbstractClass.
*/
export type ClassesStaticMembers<Classes extends readonly AbstractClass<any>[]> = (
Classes extends [infer Class, ...infer Rest]
? Class extends AbstractClass<any>
? Rest extends AbstractClass<any>[]
? [StaticMembers<Class>, ...ClassesStaticMembers<Rest>]
: never
: never
: []
)
/**
* Represents an intersection of static members of the provided classes.
* @template Classes - An array of classes extending AbstractClass.
*/
export type ClassesStaticMembersIntersection<Classes extends readonly AbstractClass<any>[]> = (
Classes extends [infer Class, ...infer Rest]
? Class extends AbstractClass<any>
? Rest extends AbstractClass<any>[]
? StaticMembers<Class> & ClassesStaticMembersIntersection<Rest>
: never
: never
: {}
)

2
src/util/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from "./class"
export * from "./inheritance"

40
src/util/inheritance.ts Normal file
View File

@@ -0,0 +1,40 @@
/**
* Represents the common keys between two types.
* @template A - The first type.
* @template B - The second type.
*/
export type CommonKeys<A, B> = Extract<keyof A, keyof B>
/**
* Merges an inheritance tree defined by an array of types, considering overrides.
* @template T - An array of types representing the inheritance tree.
*/
export type MergeInheritanceTree<T extends readonly any[]> = (
T extends [infer Super, infer Self, ...infer Rest]
? Pick<Self, CommonKeys<Self, Super>> extends Pick<Super, CommonKeys<Self, Super>>
? MergeInheritanceTree<[
Omit<Super, CommonKeys<Self, Super>> & Self,
...Rest,
]>
: never
: T extends [infer Self]
? Self
: void
)
/**
* Merges an inheritance tree defined by an array of types without allowing overrides.
* @template T - An array of types representing the inheritance tree.
*/
export type MergeInheritanceTreeWithoutOverriding<T extends readonly any[]> = (
T extends [infer Super, infer Self, ...infer Rest]
? Pick<Self, CommonKeys<Self, Super>> extends Pick<Super, CommonKeys<Self, Super>>
? MergeInheritanceTreeWithoutOverriding<[
Super & Self,
...Rest,
]>
: never
: T extends [infer Self]
? Self
: void
)