// Three formats. Same bugs. Open/Closed Principle // Teaching excerpts; see the explanation and boundaries on the episode page. // One method, different output type Report = { bugs: number }; interface Exporter { format(report: Report): string; } // Each object owns one format class JsonExporter implements Exporter { format(r: Report) { return JSON.stringify(r); } } class CsvExporter implements Exporter { format(r: Report) { return `bugs\r\n${r.bugs}`; } } // Choose the object, then call it const exporters = { json: new JsonExporter(), csv: new CsvExporter(), }; type Kind = keyof typeof exporters; const exportReport = (kind: Kind, r: Report) => exporters[kind].format(r); exportReport('csv', { bugs: 3 }); // Extend at the chosen boundary class MarkdownExporter implements Exporter { format(r: Report) { return `**Bugs:** ${r.bugs}`; } }