From 92645bfd6b782c33eb0a3d0df13376f4089b3508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 27 Jan 2024 18:45:55 +0100 Subject: [PATCH] Inheritance util --- src/tests.ts | 53 ++++++++------------------------- src/util/class.ts | 66 +++++++++++++++++++++++++++++++++++++++++ src/util/index.ts | 2 ++ src/util/inheritance.ts | 40 +++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 41 deletions(-) create mode 100644 src/util/class.ts create mode 100644 src/util/index.ts create mode 100644 src/util/inheritance.ts diff --git a/src/tests.ts b/src/tests.ts index ac733c4..87609f0 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,6 @@ -import { AbstractClass } from "type-fest" +import { AbstractClass, UnionToIntersection } from "type-fest" import { expresses, extendsAndExpresses, trait } from "." +import { ClassesInstances, ClassesInstancesIntersection, ClassesStaticMembers, MergeInheritanceTree, MergeInheritanceTreeWithoutOverriding } from "./util" const Identifiable = () => @@ -92,46 +93,16 @@ class Test3 { } -type CommonKeys = Extract - -type Extend = ( - T extends [infer Super, infer Self, ...infer Rest] - ? Pick> extends Pick> - ? Extend<[ - Omit> & Self, - ...Rest, - ]> - : never - : T extends [infer Self] - ? Self - : "Empty array" -) - -type ClassesInstances = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? [InstanceType, ...ClassesInstances] - : never - : [] -) - -type StaticMembers> = ( - Omit -) - -type ClassesStaticMembers = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? [StaticMembers, ...ClassesStaticMembers] - : never - : [] -) - type ExtendClasses[]> = ( AbstractClass< - Extend> + // Extend> + MergeInheritanceTreeWithoutOverriding< + ClassesInstances + > > & - Extend> + MergeInheritanceTree< + ClassesStaticMembers + > ) @@ -140,13 +111,13 @@ type MixedTestProto = ExtendClasses<[ typeof Test2, typeof Test3, ]> - declare const MixedTestProto: MixedTestProto -class MixedTest extends MixedTestProto {} +class MixedTest extends MixedTestProto { +} MixedTest.prototype -new MixedTest().name +new MixedTest().status.expiresAt // type MixedTestTraitsProto = Class< // Extend2, diff --git a/src/util/class.ts b/src/util/class.ts new file mode 100644 index 0000000..325aba5 --- /dev/null +++ b/src/util/class.ts @@ -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 [infer Class, ...infer Rest] + ? Class extends AbstractClass + ? Rest extends AbstractClass[] + ? [InstanceType, ...ClassesInstances] + : never + : never + : [] +) + +/** + * Represents an intersection of instances of the provided classes. + * @template Classes - An array of classes extending AbstractClass. + */ +export type ClassesInstancesIntersection[]> = ( + Classes extends [infer Class, ...infer Rest] + ? Class extends AbstractClass + ? Rest extends AbstractClass[] + ? InstanceType & ClassesInstancesIntersection + : never + : never + : {} +) + +/** + * Represents the static members of a class. + * @template Class - A class extending AbstractClass. + */ +export type StaticMembers> = ( + Omit +) + +/** + * Represents an array of static members corresponding to the provided classes. + * @template Classes - An array of classes extending AbstractClass. + */ +export type ClassesStaticMembers[]> = ( + Classes extends [infer Class, ...infer Rest] + ? Class extends AbstractClass + ? Rest extends AbstractClass[] + ? [StaticMembers, ...ClassesStaticMembers] + : 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 [infer Class, ...infer Rest] + ? Class extends AbstractClass + ? Rest extends AbstractClass[] + ? StaticMembers & ClassesStaticMembersIntersection + : never + : never + : {} +) diff --git a/src/util/index.ts b/src/util/index.ts new file mode 100644 index 0000000..05e8a4a --- /dev/null +++ b/src/util/index.ts @@ -0,0 +1,2 @@ +export * from "./class" +export * from "./inheritance" diff --git a/src/util/inheritance.ts b/src/util/inheritance.ts new file mode 100644 index 0000000..a179d78 --- /dev/null +++ b/src/util/inheritance.ts @@ -0,0 +1,40 @@ +/** + * Represents the common keys between two types. + * @template A - The first type. + * @template B - The second type. + */ +export type CommonKeys = Extract + +/** + * 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 [infer Super, infer Self, ...infer Rest] + ? Pick> extends Pick> + ? MergeInheritanceTree<[ + Omit> & 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 [infer Super, infer Self, ...infer Rest] + ? Pick> extends Pick> + ? MergeInheritanceTreeWithoutOverriding<[ + Super & Self, + ...Rest, + ]> + : never + : T extends [infer Self] + ? Self + : void +)