79785377

Date: 2025-10-08 10:59:32
Score: 0.5
Natty:
Report link

Experimented with the Kysely's Generated utility type mentioned by @zegarek in the OP comments. Looks like it is possible to make Kysely to work with temporal tables or rather with tables with autogenerated values.

The type for each table having autogenerated values must be altered and one cannot directly use the type inferred by zod. Instead the type needs to be modified. In my case all my temporal tables are following the same pattern, so I created the following wrapper

type TemporalTable<
  T extends {
    versionId: number
    validFrom: Date
    validTo: Date | null
    isCurrent: boolean
  },
> = Omit<T, 'versionId' | 'validFrom' | 'validTo' | 'isCurrent'> & {
  versionId: Generated<number>
  validFrom: Generated<Date>
  validTo: Generated<Date | null>
  isCurrent: Generated<boolean>
}

Now the type for each table is wrapped with this

const TemporalTableSchema = z.object({
  versionId: z.number(),
  someId: z.string(),
  someData: z.string(),
  validFrom: z.coerce.date(),
  validTo: z.coerce.date().optional().nullable(),
  isCurrent: z.boolean()
})

type TemporalTableSchema = TemporalTable<z.infer<typeof TemporalTableSchema>>

Now when defining the database type to give to Kysely I need to write it manually

const MyDatabase = z.object({
  table1: Table1Schema,
  temporalTable: TemporalTableSchema
})

type MyDatabase = {
  table1: z.infer<typeof Table1Schema>,
  temporalTable: TemporalTableSchema,
  // alternatively you can wrap the type of the table into the temporal type wrapper here
  anotherTemporalTable: TemporalTable<z.infer<typeof AnotherTemporalTable>>
}

So basically you need to write the type for the database by hand, wrap the necessary table types with the wrapper. You can't just simply compose the zod object for the database, infer its type and then use that type as the type for your database.

Reasons:
  • Blacklisted phrase (0.5): I need
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @zegarek
  • Self-answer (0.5):
Posted by: zaplec