This commit is contained in:
53
src/tests.ts
53
src/tests.ts
@@ -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
66
src/util/class.ts
Normal 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
2
src/util/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./class"
|
||||||
|
export * from "./inheritance"
|
||||||
40
src/util/inheritance.ts
Normal file
40
src/util/inheritance.ts
Normal 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
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user