Comparison
SheetJS, ExcelJS and typed-xlsx can all write .xlsx files. They differ in what you write.
With SheetJS or ExcelJS you place values into cells. With typed-xlsx you describe a report as a typed schema, and the library places the cells. That makes typed-xlsx narrower, it only writes reports, and much stricter about them.
At a glance
| typed-xlsx | SheetJS (Community) | ExcelJS | |
|---|---|---|---|
| You write | a schema typed against your rows | arrays and cell objects | workbook, row and cell objects |
Reads .xlsx | no | yes | yes |
| Other formats | no | CSV, XLS, ODS and many more | CSV |
| Cell styles on write | yes | in SheetJS Pro | yes |
| Formulas | typed DSL, references checked by TypeScript | strings | strings |
| Summary and totals rows | declared per column | written by hand | written by hand |
| Native Excel tables | yes | no | yes |
| Native charts | typed marks over your tables | no | no |
| Pivot tables | typed fields, with pivot charts | no | basic |
| Streaming write | same schema, batch commits | not for .xlsx | separate streaming writer |
| Runtime dependencies | none | none | several |
Where typed-xlsx is the better fit
The report is the contract. Columns, headers, formulas, styles and summaries live in one schema typed against your row type. Renaming a field breaks the build, not the export.
Formulas stay correct when columns move. You write refs.column("qty").mul(refs.column("unitPrice")); typed-xlsx writes =(C2*D2), or a structured reference inside an Excel table. Referencing a column that doesn't exist, or one declared later, is a type error.
One schema, many exports. The same schema serves different row sets, a different column selection per audience, a different theme, or a native Excel table, without copying column definitions.
Big exports use the same code. createWorkbookStream() takes the same schema as createWorkbook(). See Benchmarks for measured throughput.
Report features are built in. Grouped headers, sub-row expansion, summary rows, badges, checkboxes, sparklines, images, hyperlinks, validation dropdowns, conditional formats and protection are schema options rather than cell-by-cell code. Native charts and pivot tables are declared from the tables you already have, with their columns checked by TypeScript.
Where SheetJS or ExcelJS is the better fit
- Reading files. typed-xlsx only writes. To parse uploads or import spreadsheets, use SheetJS or ExcelJS.
- Other formats. SheetJS reads and writes far more formats than
.xlsx. - Editing an existing workbook. Opening a file, changing it and saving it back is outside typed-xlsx's scope.
- Free-form sheets. When the sheet isn't a table of records (a form, a dashboard laid out cell by cell, notes and rich text), a cell API is the more direct tool.
Quick Start
Build an invoice report with formula columns, a totals row and status badges, then export it buffered and streamed from the same schema.
Schema Modes
Report mode writes a laid-out range with titles and summary rows; excel-table mode writes a native Excel table with filters and a totals row. How to choose.