Theo's Typesafe CultTTC
Theo's Typesafe Cult3y ago
8 replies
Sz

key paths for recursive nested types

Hey all, I have the following type
type Schema = {
  name: string,
  description: string,
  type: "string" | "number" | "boolean" | "array" | "object",
  enum?: string[],
  properties?: Schema[],
  items?: Omit<Schema, "name" | "description">,
}

const schema: z.ZodType<Schema> = z.object({
  name: z.string(),
  description: z.string(),
  type: z.union([z.literal("string"), z.literal("number"), z.literal("boolean"), z.literal("array"), z.literal("object")]),
  enum: z.array(z.string()).optional(),
  properties: z.array(z.lazy(() => schema)).optional(),
  items: z.lazy(() => schema).optional(),
})

and am trying to build out a type that represents all the possible key paths that could be created through the nesting of properties or items.

I've tried a few patterns and have had chatGPT spit types out, but none of them seem to work. The closest thing I could get to was this
type Keypath<T> = T extends { properties: Schema[] }
  ? { [K in keyof T['properties']]: `properties.${K}` | Keypath<T['properties'][K]> }[keyof T['properties']]
  : T extends { items: Omit<Schema, "name" | "description"> }
  ? `items.${number}` | Keypath<T['items']>
  : never;


For now, I've settled to using regex through zod to represent the type
const formSchemaKeyPath = z.string().regex(/^(functions)((\.[0-9]+)(\.(properties|items)))*/)


If anyone knows the solution to this, please do let me know
Was this page helpful?