js-partial-classes
Version:
A utility package for supplementing main classes with methods from partial classes, supporting both static and instance methods.
131 lines (123 loc) • 3.69 kB
text/typescript
/**
* TypeScript utility types for partial class supplementation.
*
* This module provides type utilities that help TypeScript understand the combined
* structure of main classes and partial classes after supplementation.
*
* @module types
* @since 1.0.0
*/
/**
* Recursively combines instance types from an array of class constructors.
*
* This utility type takes an array of class constructors and merges their
* instance types together, creating a union type that represents all possible
* instance properties and methods.
*
* @template T - Array of class constructors
* @returns Union type of all instance types
*
* @example
* ```typescript
* class User { name: string; }
* class Admin { role: string; }
*
* type UserOrAdmin = CombineInstances<[typeof User, typeof Admin]>;
* // Result: { name: string } | { role: string }
* ```
*
* @since 1.0.0
*/
export type CombineInstances<T extends any[]> = T extends [infer First, ...infer Rest]
? First & CombineInstances<Rest>
: unknown;
/**
* Extracts instance types from an array of class constructors.
*
* This utility type maps over an array of class constructors and extracts
* the instance type of each class, creating an array of instance types.
*
* @template T - Array of class constructors
* @returns Array of instance types
*
* @example
* ```typescript
* class User { name: string; }
* class Admin { role: string; }
*
* type InstanceArray = Instances<[typeof User, typeof Admin]>;
* // Result: [{ name: string }, { role: string }]
* ```
*
* @since 1.0.0
*/
export type Instances<T extends Array<new (...args: any) => any>> = {
[K in keyof T]: T[K] extends new (...args: any) => infer R ? R : never;
};
/**
* Combines multiple class constructors into a single combined type.
*
* This is the main utility type that combines the static and instance
* properties of multiple classes. It's particularly useful for creating
* type definitions that represent classes after supplementation with
* partial classes.
*
* @template T - Array of class constructors to combine
* @returns Combined type with all static and instance properties
*
* @example
* ```typescript
* import { supplement } from 'js-partial-classes';
*
* class Home {
* constructor() {
* supplement(this, import('./HomePartial'));
* }
*
* homeMethod() { return 'home'; }
* }
*
* class HomePartial {
* static staticMethod() { return 'static'; }
* partialMethod() { return 'partial'; }
* }
*
* // Create a type that represents the combined class
* export type HomeFull = Combine<[typeof Home, typeof HomePartial]>;
*
* // HomeFull now includes:
* // - All static methods from Home and HomePartial
* // - All instance methods from Home and HomePartial
* // - All properties from both classes
* ```
*
* @example
* ```typescript
* // For multiple partial classes
* class UserService {
* constructor() {
* supplement(this, import('./ValidationPartial'));
* supplement(this, import('./UtilitiesPartial'));
* }
* }
*
* class ValidationPartial {
* static validateEmail(email: string): boolean { return true; }
* validateRequired(value: any): boolean { return true; }
* }
*
* class UtilitiesPartial {
* static formatDate(date: Date): string { return date.toISOString(); }
* formatCurrency(amount: number): string { return `$${amount}`; }
* }
*
* export type UserServiceFull = Combine<[
* typeof UserService,
* typeof ValidationPartial,
* typeof UtilitiesPartial
* ]>;
* ```
*
* @since 1.0.0
*/
export type Combine<T extends Array<new (...args: any) => any>> = CombineInstances<Instances<T>>;