
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
js-partial-classes
Advanced tools
A utility package for supplementing main classes with methods from partial classes, supporting both static and instance methods.
A utility package for supplementing main classes with methods from partial classes, supporting both static and instance methods.
.ts file handlingnpm install js-partial-classes
import { supplement } from 'js-partial-classes';
class MainClass {
static {
// Supplement with partial class during static initialization
supplement(this, import('./partial-class.js'));
}
constructor() {
this.name = 'Main';
}
mainMethod() {
return 'Main method';
}
}
// The supplement function will await the dynamic import automatically
// Now MainClass has methods from the partial class
console.log(MainClass.staticMethod()); // Available from partial class
const instance = new MainClass();
console.log(instance.instanceMethod()); // Available from partial class
import { supplement } from 'js-partial-classes';
class MainClass {
static {
// Supplement with multiple partial classes during static initialization
supplement(this, import('./partials/validation.js'));
supplement(this, import('./partials/utilities.js'));
supplement(this, import('./partials/api.js'));
}
// ... main class implementation
}
import { supplementAll, myDir } from 'js-partial-classes';
class MainClass {
static {
// Load all .js and .ts files from a directory
// Note: supplementAll requires absolute paths
const partialClassesDir = myDir(import.meta.url) + '/partial-classes';
supplementAll(this, partialClassesDir);
}
// ... main class implementation
}
supplement(mainClass, partialClass)Supplements a main class with methods from a partial class.
Parameters:
mainClass (Class): The target class to be supplementedpartialClass (Class | string): The partial class or path to the partial class moduleReturns: Promise
Behavior:
partialClass to mainClasspartialClass.prototype to mainClass.prototypesupplementAll(mainClass, directory)Supplements a main class with methods from all partial classes in a directory.
Parameters:
mainClass (Class): The target class to be supplementeddirectory (string): The absolute directory path to scan for partial class filesReturns: Promise<Record<string, any>>
Behavior:
.js, .ts, .mjs, and .cjs filesmyDir(url)Utility function to get the directory path from a file URL. Essential for ES modules to obtain absolute paths.
Parameters:
url (string): The import.meta.url or file URLReturns: string - The directory path
Example:
import { myDir } from 'js-partial-classes';
// Get current directory in ES module
const currentDir = myDir(import.meta.url);
// Use with supplementAll
const partialClassesDir = myDir(import.meta.url) + '/partial-classes';
supplementAll(MainClass, partialClassesDir);
iterateDescriptors(cls, callback)Utility function to iterate over class descriptors.
Parameters:
cls (Class): The class to iterate overcallback (Function): Callback function called with [key, descriptor] pairsMethod-Only Support: Partial classes can only contain methods (both static and instance). Properties, getters, setters, and other class members are not supported.
Constructor Exclusion: The constructor method is automatically excluded from the supplementation process.
Method Override: If a method with the same name already exists in the main class, it will be overridden by the partial class method.
No Property Copying: Only methods are copied; properties and other descriptors are not transferred.
The library provides powerful utility types that help TypeScript understand the combined structure of classes after supplementation.
import { supplement, Combine } from 'js-partial-classes';
class Home {
static {
supplement(this, 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 methods from both classes
const home = new Home() as HomeFull;
home.homeMethod(); // ✅ Available
home.partialMethod(); // ✅ Available
Home.staticMethod(); // ✅ Available
import { supplement, Combine } from 'js-partial-classes';
class UserService {
static {
supplement(this, ValidationPartial);
supplement(this, UtilitiesPartial);
}
addUser(user: any) { this.users.push(user); }
}
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}`; }
}
// Combine all classes into one type
export type UserServiceFull = Combine<[
typeof UserService,
typeof ValidationPartial,
typeof UtilitiesPartial
]>;
// UserServiceFull now has all methods from all classes
const service = new UserService() as UserServiceFull;
service.validateEmail('test@example.com'); // ✅ Available
service.formatDate(new Date()); // ✅ Available
service.formatCurrency(1234.56); // ✅ Available
as Operator// Simply use the 'as' operator for type assertion
const user = new UserService() as UserServiceFull;
// Now TypeScript knows about all supplemented methods
user.validateEmail('test@example.com');
user.formatDate(new Date());
user.addUser({ name: 'John' });
// partial-classes/validation.ts
export default class ValidationPartial {
static validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
validateRequired(value: any): boolean {
return value !== null && value !== undefined && value !== '';
}
}
// partial-classes/utilities.ts
export default class UtilitiesPartial {
static formatDate(date: Date): string {
return date.toISOString().split('T')[0];
}
formatCurrency(amount: number): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount);
}
}
// main-class.ts
import { supplementAll, myDir, Combine } from 'js-partial-classes';
class UserService {
static {
// Load all partial classes from the directory (supports .js, .ts, .mjs, .cjs)
// Note: supplementAll requires absolute paths
const partialClassesDir = myDir(import.meta.url) + '/partial-classes';
supplementAll(this, partialClassesDir);
}
constructor() {
this.users: any[] = [];
}
addUser(user: any): void {
this.users.push(user);
}
}
// Define the partial classes for type combination
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}`; }
}
// Create a combined type that includes all supplemented methods
export type UserServiceFull = Combine<[
typeof UserService,
typeof ValidationPartial,
typeof UtilitiesPartial
]>;
// Usage with proper typing
const service = new UserService() as UserServiceFull;
// Now TypeScript knows about all supplemented methods!
console.log(UserService.validateEmail('test@example.com')); // ✅ No @ts-ignore needed
console.log(UserService.formatDate(new Date())); // ✅ No @ts-ignore needed
console.log(service.validateRequired('hello')); // ✅ No @ts-ignore needed
console.log(service.formatCurrency(1234.56)); // ✅ No @ts-ignore needed
// validation.js
export default class ValidationPartial {
static validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
validateRequired(value) {
return value !== null && value !== undefined && value !== '';
}
}
// utilities.js
export default class UtilitiesPartial {
static formatDate(date) {
return date.toISOString().split('T')[0];
}
formatCurrency(amount) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount);
}
}
import { supplement } from 'js-partial-classes';
class UserService {
static {
// Supplement with validation and utilities during static initialization
supplement(this, import('./validation.js'));
supplement(this, import('./utilities.js'));
}
constructor() {
this.users = [];
}
addUser(user) {
this.users.push(user);
}
}
// Now UserService has all methods from both partials
const service = new UserService();
// Static methods
console.log(UserService.validateEmail('test@example.com')); // true
console.log(UserService.formatDate(new Date())); // '2024-01-15'
// Instance methods
console.log(service.validateRequired('hello')); // true
console.log(service.formatCurrency(1234.56)); // '$1,234.56'
ISC
Praveen Ranjan Keshri
FAQs
A utility package for supplementing main classes with methods from partial classes, supporting both static and instance methods.
The npm package js-partial-classes receives a total of 5 weekly downloads. As such, js-partial-classes popularity was classified as not popular.
We found that js-partial-classes demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.