Skip to content

Typed tables

matter app types writes matter-app.d.ts, or the path that types in matter.json names. It holds the SDK’s types, plus one entry for each table in the app’s space, generated from the tables as they are in Matter now. Include it in your tsconfig.json.

matter.table('Deals') is then typed, and the compiler catches what the data API would refuse at run time:

  • a table, index or field that doesn’t exist;
  • an eq that’s missing one of the index’s match fields, or names an option the field doesn’t have;
  • a range on anything but the index’s first order field, or with the wrong type of value;
  • a sort or filter on a field that doesn’t exist;
  • groupCount by a field that isn’t one of the index’s match fields;
  • upsert on an index that isn’t unique;
  • write values of the wrong type, or several people for a field that holds one.

Rows come back typed. row.values.Stage is 'Lead' | 'Won' | …, and fields that may be empty are optional. Option names in row values also accept any string, since someone may add an option in Matter after you generated the types. Writes, eq and filters accept only the options the field has, unless a write passes { createOptions: true } to add the ones it names (see Options).

Without generated types, every table is untyped.

  • matter app dev regenerates the file whenever the space’s tables change while it runs, so a field added in Matter is in your types seconds later.
  • matter app deploy warns when the file is out of date.
  • Otherwise, run matter app types again after changing tables or updating Matter.

Don’t edit the file: it’s rewritten each time.

The types export what you need to write typed helpers, such as React hooks:

Type What it is
Tables Every table of the space, by name.
TableRead<T> Any read of a table: through one of its indexes, with that index’s own checks, or a scan.
TableMatch<T> Rows matching any of a table’s indexes, for count, exists and ids.
TableGroupRead<T> A groupCount through any of a table’s indexes.
TypedGroups<T, I> What groupCount gives through index I.
Row<Values> A row with these values.
Person, LinkedRow, Attachment The shapes of those values.
import type { Row, TableRead, Tables } from '/_matter/sdk.js'
type TableName = keyof Tables & string
declare function useQuery<N extends TableName>(
table: N,
read: TableRead<Tables[N]> | null,
): Row<Tables[N]['values']>[]
const LEADS: TableRead<Tables['Deals']> = { index: 'by_stage', eq: { Stage: 'Lead' } }

In a worker or tools written in TypeScript, type the module with the same file:

const { default: matter } = (await import(process.env.MATTER_SDK!)) as typeof import('@matter/app-sdk')