Skip to content

Conversation

@swalha1999
Copy link

Problem

When using function refinements in createInsertSchema, the type inference was not correctly applying ZodOptional for:

  • Nullable columns (should be optional since they can be omitted)
  • NotNull columns with defaults (should be optional since defaults will be used)

This caused a type mismatch where the inferred type was string | null but the runtime schema correctly produced string | null | undefined.

Example

const blogPost = pgTable("blog_post", {
  id: uuid("id").primaryKey().defaultRandom(),
  title: text("title").notNull(),
  metaTitle: text("meta_title"), // nullable, no default
});

const insertSchema = createInsertSchema(blogPost, {
  metaTitle: (schema) => schema.max(60, "Too long"),
});

// Before fix: metaTitle inferred as `string | null` (missing undefined)
// After fix: metaTitle inferred as `string | null | undefined`

Solution

The fix aligns HandleRefinement type with HandleInsertColumn logic:

  • For nullable columns: z.ZodOptional<z.ZodNullable<TSchema>>
  • For notNull with default: z.ZodOptional<TSchema>
  • For notNull without default: TSchema (required)

Changes

  • Updated HandleRefinement type in drizzle-zod/src/schema.types.internal.ts

Testing

All 70 existing drizzle-zod tests pass.

…nullable/default columns

When using function refinements in createInsertSchema, the type inference
was not correctly applying ZodOptional for:
- Nullable columns (should be optional since they can be omitted)
- NotNull columns with defaults (should be optional since defaults will be used)

This caused a type mismatch where the inferred type was `string | null`
but the runtime schema was `string | null | undefined`.

The fix aligns HandleRefinement with HandleInsertColumn logic:
- For nullable columns: z.ZodOptional<z.ZodNullable<TSchema>>
- For notNull with default: z.ZodOptional<TSchema>
- For notNull without default: TSchema (required)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant