15 minlesson

Prototype Pattern in TypeScript

Prototype Pattern in TypeScript

Generic Cloneable Interface

typescript
1interface Cloneable<T> {
2 clone(): T;
3}
4
5abstract class Prototype<T extends Prototype<T>> implements Cloneable<T> {
6 abstract clone(): T;
7}

Prototype Registry

Store and retrieve prototypes by key:

typescript
1class PrototypeRegistry<T extends Cloneable<T>> {
2 private prototypes = new Map<string, T>();
3
4 register(key: string, prototype: T): void {
5 this.prototypes.set(key, prototype);
6 }
7
8 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}
14
15// Usage
16const 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'));
19
20const newHome = registry.get('home');
21newHome.street = '789 New St';

With Immutable Data

typescript
1class ImmutableAddress {
2 constructor(
3 readonly street: string,
4 readonly city: string,
5 readonly state: string,
6 readonly postalCode: string
7 ) {}
8
9 // Return new instance with modifications
10 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.postalCode
16 );
17 }
18}
19
20const 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:

typescript
1class ShipmentPrototypeFactory {
2 private templates = new Map<string, Shipment>();
3
4 registerTemplate(name: string, template: Shipment): void {
5 this.templates.set(name, template);
6 }
7
8 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