Skip to content

fix(drizzle-zod): default TCoerce to undefined in createSchemaFactory#5973

Open
tsushanth wants to merge 1 commit into
drizzle-team:mainfrom
tsushanth:fix/drizzle-zod-schema-factory-tcoerce-default
Open

fix(drizzle-zod): default TCoerce to undefined in createSchemaFactory#5973
tsushanth wants to merge 1 commit into
drizzle-team:mainfrom
tsushanth:fix/drizzle-zod-schema-factory-tcoerce-default

Conversation

@tsushanth

Copy link
Copy Markdown

Fixes #5968

Root cause

createSchemaFactory has a generic TCoerce with no default:

export function createSchemaFactory<
  TCoerce extends Partial<Record<...>> | true | undefined,
>(options?: CreateSchemaFactoryOptions<TCoerce>)

When the caller omits the coerce option (e.g. createSchemaFactory({ zodInstance: z })), TypeScript cannot infer TCoerce from the argument and falls back to the full constraint bound: Partial<Record<...>> | true | undefined.

This union propagates into GetZodType, where CanCoerce<TCoerce, 'string'> distributes over the union and returns boolean. The conditional type then produces z.ZodCoercedString | z.ZodString for string columns.

BuildRefineField is distributive over its input, so it produces two function overloads with incompatible parameter types:

((schema: z.ZodCoercedString) => z.ZodType) | ((schema: z.ZodString) => z.ZodType) | z.ZodType

TypeScript cannot contextually type a callback against a union of function types with different parameter types, so schema widens to any (ts 7006).

The top-level createInsertSchema / createSelectSchema / createUpdateSchema exports explicitly use CreateInsertSchema<undefined>, which is why they work correctly.

Fix

Add = undefined as the default type parameter for TCoerce in createSchemaFactory. When no coerce option is provided, TCoerce now defaults to undefined instead of widening to the full constraint bound — matching the behaviour of the top-level exports.

When no coerce option is passed to createSchemaFactory, TypeScript falls
back to the full constraint bound for TCoerce rather than undefined.
This causes GetZodType to distributively return a union of coerced and
non-coerced types (e.g. ZodCoercedString | ZodString), which makes the
BuildRefineField callback parameter unresolvable — TypeScript widens to
any (ts 7006).

Adding = undefined as a default type parameter matches the TCoerce used
by the top-level createInsertSchema/createSelectSchema/createUpdateSchema
exports, restoring proper type inference for refinement callbacks when
createSchemaFactory is used without a coerce option.
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.

[BUG]: drizzle-orm/zod createSchemaFactory breaks refine callback type inference (implicit 'any')

1 participant