Lab
Prototype
type Query = { minutes: number; filters: string[] };
type Definition = Readonly<{ name: string; version: number }>;
class IncidentCard {
id: string;
query: Query;
definition: Definition;
preview: number | null;
constructor(
id: string,
query: Query,
definition: Definition,
preview: number | null,
) {
this.id = id;
this.query = query;
this.definition = definition;
this.preview = preview;
}
// The prototype: the card decides what its duplicate owns and shares.
duplicate(newId: string): IncidentCard {
const query = {
minutes: this.query.minutes,
filters: [...this.query.filters],
};
return new IncidentCard(newId, query, this.definition, null);
}
edit(minutes: number, firstFilter: string): void {
this.query.minutes = minutes;
this.query.filters[0] = firstFilter;
this.preview = null;
}
}
const definition = Object.freeze({ name: 'Incident feed', version: 1 });
const query = { minutes: 15, filters: ['http-5xx', 'timeout'] };
const source = new IncidentCard('preset-api', query, definition, 42);
// Duplicate the configured card, edit the copy, then copy the copy.
const a = source.duplicate('card-a');
a.edit(30, 'latency');
const b = a.duplicate('card-b');
const sharedDefinition = a.definition === source.definition;
function show(card: IncidentCard) {
const filters = card.query.filters.join(',');
const preview = card.preview ?? '-';
console.log(`${card.id}: ${card.query.minutes}m ${filters} preview=${preview}`);
}
show(source);
show(a);
show(b);
const about = `${definition.name} v${definition.version}`;
console.log(`definition: ${about}, shared=${sharedDefinition}`);
A configured card copies itself. Query data, shared definition and preview have different policies.
At this recorded stop
Bindings appear as the program creates them.
— means unavailable; none and quiet are recorded values.Each binding keeps its place. Equal labels do not imply one object. Inspect recorded objects for all fields. Dimmed rows retain earlier observations.