ARTICLE AD BOX
Given a library exporting Zod schemas (living in their own separate files) defining a recursive table header structure.
Starting with the root schema
const columnsConfigurationSchema = z.array(columnConfigurationSchema).min(1);where each element is either a group or a leaf
const columnConfigurationSchema = z.union([ columnGroupConfigurationSchema, leafColumnConfigurationSchema, ]);I also added a helper function to check if a column is a column group
function isColumnGroup(column: ColumnConfiguration): column is ColumnGroupConfiguration { return "children" in column; }A column group contains some group fields and child columns, so things start getting recursive
const columnGroupConfigurationSchema = z.object({ // ...group fields... get children() { return columnsConfigurationSchema; }, });A leaf column can be of multiple types (based on field type) but this is just an example
const leafColumnConfigurationSchema = z.discriminatedUnion("type", [ workItemColumnConfigurationSchema, computedColumnConfigurationSchema, ]);where a WorkItemColumn represents
const workItemColumnConfigurationSchema = z.object({ // type field (z.ZodLiteral<"workItem">) // other fields });and a ComputedColumn represents
const computedColumnConfigurationSchema = z.object({ // type field (z.ZodLiteral<"computed">) // other fields });Since I'm using the getter property TypeScript and Zod are able to handle the recursive schema. But when consuming the library at some places TypeScript doesn't know how to resolve the types correctly. For example
function getColspan(columnConfiguration: ColumnConfiguration) { if(!isColumnGroup(columnConfiguration)) { return 1; } // children should not be of type any here return columnConfiguration.children.reduce((colspanSum, currentChildColumn) => colspanSum + getColspan(currentChildColumn), 0); }The type guard checks if a given element is a column group. But still the children field is of type `any` although I would expect it to be of type `ColumnsConfiguration`.
How to fix the schema so TypeScript knows how to handle it correctly?
