drizzle-team / drizzle-team/drizzle-orm
[BUG]:createInsertSchema with refinements doesn't handle type inference properly with optional columns (drizzle-typebox)
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
### Report hasn't been filed before.
- [x] I have verified that the bug I'm about to report hasn't been filed before.
### What version of `drizzle-orm` are you using?
0.44.4
### What version of `drizzle-kit` are you using?
0.31.4
### Other packages
drizzle-typebox@0.3.3
### Describe the Bug
### What is the undesired behavior?
When using `createInsertSchema` with refinements, all fields in the generated schema are inferred as **required**, even if they should remain optional or nullable.
Specifically:
- `Id` and `UpdatedTime` (auto-increment / default-now) should be optional.
- `Content` (nullable) should be optional.
- Only `RequiredContent` should remain required.
Instead, the refinement step seems to remove optionality and forces all fields to required.
---
### Steps to reproduce
```js
//@ts-check
import { describe, test, expect } from "vitest";
import { createInsertSchema } from "drizzle-typebox";
import * as c from "drizzle-orm/mysql-core";
import { TypeGuard as G } from "@sinclair/typebox";
const simpleTable = c.mysqlTable("simple_table", {
Id: c.int("id").autoincrement().primaryKey(),
Content: c.varchar({ length: 120 }),
RequiredContent: c.varchar({ length: 120 }).notNull(),
UpdatedTime: c.timestamp("UpdatedTime", { mode: 'string' })
.defaultNow()
.onUpdateNow()
.notNull(),
});
test("refinements should not affect optionality", () => {
const schema = createInsertSchema(simpleTable, {
// dummy refinements
Content: (s) => s,
Id: (s) => s,
RequiredContent: (s) => s,
UpdatedTime: (s) => s,
});
const { Content, Id, RequiredContent, UpdatedTime } = schema.properties;
// These pass at runtime but fail in inferred types
expect(G.IsOptional(Id)).toEqual(true);
expect(G.IsOptional(UpdatedTime)).toEqual(true);
expect(G.IsOptional(Content)).toEqual(true);
expect(G.IsOptional(RequiredContent)).toEqual(false);
});
```
The resulting inference resolved to ...
```ts
TObject<{
Id: TInteger;
Content: TUnion<[TString, TNull]>;
RequiredContent: TString;
UpdatedTime: TString;
}>
```
### Desired result
expected Refinements to preserve existing optionality/nullability of columns.
The generated schema should look like:
```ts
TObject<{
Id: TOptional;
Content: TOptional>;
RequiredContent: TString; // required
UpdatedTime: TOptional;
}>
```
Contributor guide
Assessment
This issue has not been assessed yet.