Skip to content

Shared Types Style Guide

All shared types in HoneyGrid must be derived from validators to ensure runtime type safety. There are two paths for type creation:

For database entities, types flow from Drizzle schema to Zod validators to TypeScript types:

Drizzle Schema --> Zod Validator --> TypeScript Type

Example using Workspaces:

  1. Define Drizzle schema:
export const Workspaces = table('Workspaces', {
id: text().primaryKey().notNull(),
name: text().notNull(),
// ... other fields
})
  1. Create Zod validators using drizzle-zod:
export const workspaceSelectValidator = createSelectSchema(Workspaces)
export const workspaceInsertValidator = createInsertSchema(Workspaces).omit({
createdAt: true,
id: true,
})
  1. Derive TypeScript types:
export type WorkspaceSelect = typeof Workspaces.$inferSelect
export type WorkspaceInsert = z.infer<typeof workspaceInsertValidator>

For non-database types, define Zod validators first then derive TypeScript types:

Zod Validator --> TypeScript Type

Example:

export const UserPreferencesValidator = z.object({
theme: z.enum(['light', 'dark']),
notifications: z.boolean(),
})
export type UserPreferences = z.infer<typeof UserPreferencesValidator>
  1. Always suffix validators with Validator
  2. Place related schemas, validators and types in the same directory
  3. Export both validators and types for runtime validation
  4. Use .omit() and .extend() to customize validators when needed
  5. Keep schema definitions as the source of truth
  6. Co-locate related types in feature-specific files
honeygrid-types/
├── schema/ # Drizzle schema definitions
├── validators-and-types/ # Validators and derived types
└── index.ts # Public exports
  • Use Select suffix for read operations
  • Use Insert suffix for create operations
  • Use Update suffix for partial updates
  • Omit auto-generated fields from insert validators
  • Define enums in schema when possible for DB constraints