Schema Context
createExcelSchema<Row, Context>() declares a schema-wide runtime context object.
That object is part of the schema contract. It is not tied to one feature and it is not only for dynamic(...).
What schema context is for
Schema context is useful when some export-time inputs are known outside the row itself, such as:
- region or territory lists
- reporting periods
- currency or locale preferences
- feature flags or presentation options
- lookup maps used by formulas, styles, or hyperlinks
Anywhere the API exposes ctx, it is the same schema-level object.
Where ctx is available
ctx flows from the table-level context option into every callback that receives it:
Depending on the callback type, ctx can be used in:
conditiondynamic(...)- accessor callbacks
transformformatstylehyperlink- formula callbacks
import { createExcelSchema } from "typed-xlsx";
type Deal = {
amount: number;
region: "EMEA" | "AMER" | "APAC";
};
type SchemaContext = {
featuredRegion: Deal["region"];
currencySymbol: string;
};
const schema = createExcelSchema<Deal, SchemaContext>()
.column("regionOnly", {
accessor: "region",
condition: ({ ctx }) => ctx.featuredRegion === "EMEA",
})
.column("amount", {
accessor: "amount",
format: ({ ctx }) => `${ctx.currencySymbol}#,##0.00`,
style: ({ row, ctx }) => ({
font: {
bold: row.region === ctx.featuredRegion,
},
}),
})
.build();
Context is required per contextful schema
If a schema declares createExcelSchema<Row, Context>(), tables built from that schema must provide context.
This is true even when select excludes all dynamic scopes, because context belongs to the schema as a whole.
import { createExcelSchema, createWorkbook } from "typed-xlsx";
type Row = { name: string; orgs: number[] };
const schema = createExcelSchema<Row, { orgIds: number[] }>()
.column("name", { accessor: "name" })
.dynamic("memberships", (builder, { ctx }) => {
for (const id of ctx.orgIds) {
builder.column(`org-${id}`, { accessor: (row) => row.orgs.includes(id) });
}
})
.build();
createWorkbook()
.sheet("Sheet")
.table("sheet", {
rows: [],
schema,
select: { exclude: ["memberships"] },
});
Context shape is fully typed
Use SchemaContextOf<typeof schema> when you want to extract the required table-time context shape from a built schema.
import { createExcelSchema } from "typed-xlsx";
import type { SchemaContextOf } from "typed-xlsx";
const schema = createExcelSchema<{ name: string }, { locale: string }>()
.column("name", { accessor: "name" })
.build();
type RequiredContext = SchemaContextOf<typeof schema>;