Prototype Pattern in TypeScript
Generic Cloneable Interface
typescript1interface Cloneable<T> {2 clone(): T;3}45abstract class Prototype<T extends Prototype<T>> implements Cloneable<T> {6 abstract clone(): T;7}
Prototype Registry
Store and retrieve prototypes by key:
typescript1class PrototypeRegistry<T extends Cloneable<T>> {2 private prototypes = new Map<string, T>();34 register(key: string, prototype: T): void {5 this.prototypes.set(key, prototype);6 }78 get(key: string): T {9 const prototype = this.prototypes.get(key);10 if (!prototype) throw new Error(`No prototype: ${key}`);11 return prototype.clone();12 }13}1415// Usage16const registry = new PrototypeRegistry<AddressTemplate>();17registry.register('home', new AddressTemplate('123 Main', 'NYC', 'NY', '10001', 'US'));18registry.register('work', new AddressTemplate('456 Corp', 'NYC', 'NY', '10002', 'US'));1920const newHome = registry.get('home');21newHome.street = '789 New St';
With Immutable Data
typescript1class ImmutableAddress {2 constructor(3 readonly street: string,4 readonly city: string,5 readonly state: string,6 readonly postalCode: string7 ) {}89 // Return new instance with modifications10 with(changes: Partial<ImmutableAddress>): ImmutableAddress {11 return new ImmutableAddress(12 changes.street ?? this.street,13 changes.city ?? this.city,14 changes.state ?? this.state,15 changes.postalCode ?? this.postalCode16 );17 }18}1920const original = new ImmutableAddress('123 Main', 'NYC', 'NY', '10001');21const modified = original.with({ street: '456 Oak' });22// original unchanged, modified has new street
Factory + Prototype
Combine patterns for flexible creation:
typescript1class ShipmentPrototypeFactory {2 private templates = new Map<string, Shipment>();34 registerTemplate(name: string, template: Shipment): void {5 this.templates.set(name, template);6 }78 createFromTemplate(name: string): Shipment {9 const template = this.templates.get(name);10 if (!template) throw new Error(`Unknown template: ${name}`);11 return template.clone();12 }13}
Summary
Prototype in TypeScript:
- Use
Cloneable<T>interface for type safety - Registry pattern for template management
with()method for immutable updates- Combine with Factory for flexible creation