Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG]: drizzle-zod inferring types incorrectly #3734

Open
1 task done
kylekz opened this issue Dec 10, 2024 · 1 comment
Open
1 task done

[BUG]: drizzle-zod inferring types incorrectly #3734

kylekz opened this issue Dec 10, 2024 · 1 comment
Assignees
Labels
bug Something isn't working drizzle/zod

Comments

@kylekz
Copy link

kylekz commented Dec 10, 2024

Report hasn't been filed before.

  • 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.38.0

What version of drizzle-kit are you using?

0.0.0

Other packages

drizzle-zod@0.6.0

Describe the Bug

https://stackblitz.com/edit/vitejs-vite-nu1nvhap?file=src%2Fmain.ts

typescript 5.7.2
tsconfig (monorepo): https://gist.github.com/kylekz/806cf0d9e4ba5467b995b57e727884f8

createInsertSchema and createUpdateSchema infer/map types from the database schema incorrectly

i've added four types in the stackblitz:

  • insert with explicitly defined types (i use a custom idSchema to enforce prefixes)
  • insert without explicitly defined types
  • update with explicitly defined types
  • update without explicitly defined types

for the explicitly defined ones, it's mapping JSONContent from the value column onto the other columns

// actual
type Insert1 = {
    value: JSONContent;
    id: string;
    createdAt: string | JSONContent;
    assessmentId: string;
    controlId: string;
    image: string | JSONContent;
}
// expected
type Insert1 = {
    value: JSONContent;
    id: string;
    createdAt: string;
    assessmentId: string;
    controlId: string;
    image: string | null;
}

for the inferred/without explicitly defined types, every column is optional unknown, which seems counter intuitive

possibly related to the incorrect type mapping but i'm unable to replicate, i'm seeing a text column being given the type of string | string[]. the column above it in the definition has the type of string[] as it's a json column.

@tacomanator
Copy link
Contributor

Adding some additional info in the form of test cases. Given the following table:

import { sqliteTable, text } from "drizzle-orm/sqlite-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";

const permissionsSchema = z
  .array(z.enum(["a", "b", "c"]))
  .transform((val) => val.sort());

export const users = sqliteTable(
  "users",
  {
    name: text("name"),
    permissions: text("permissions", { mode: "json" })
      .$type<z.infer<typeof permissionsSchema>>()
      .notNull(),
  }
);

Case 1: name is receiving shape of permissions

export const schema1 = createInsertSchema(users, {
  permissions: () => permissionsSchema,
});

schema1.shape
// ZodObject<{ name: ZodNullable<ZodEffects<ZodArray<ZodEnum<["a", "b", "c"]>, "many">, ("a" | "b" | "c")[], ("a" | "b" | "c")[]>>; permissions: ZodEffects<...>; }, "strip", ZodTypeAny, { ...; }, { ...; }>.shape: {
//   name: z.ZodNullable<z.ZodEffects<z.ZodArray<z.ZodEnum<["a", "b", "c"]>, "many">, ("a" | "b" | "c")[], ("a" | "b" | "c")[]>>;
//   permissions: z.ZodEffects<z.ZodArray<z.ZodEnum<["a", "b", "c"]>, "many">, ("a" | "b" | "c")[], ("a" | "b" | "c")[]>;
// }

Case 2: adding an unused parameter somehow fixes name

export const schema2 = createInsertSchema(users, {
  // provide parameter to method but don't use it
  permissions: (unused) => permissionsSchema
});

schema2.shape.name
// z.ZodOptional<z.ZodNullable<z.ZodString>>

Case 3: without providing custom schema to permissions...

export const schema3 = createInsertSchema(users);

schema3.shape
// ZodObject<{ name: ZodOptional<ZodNullable<ZodString>>; permissions: ZodOptional<ZodObject<ZodString[], "strip", ZodTypeAny, { [x: number]: string; ... 40 more ...; readonly [Symbol.unscopables]: { ...; }; }, { ...; }>>; }, "strip", ZodTypeAny, { ...; }, { ...; }>.shape: {
//   name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
//   permissions: z.ZodOptional<z.ZodObject<z.ZodString[], "strip", z.ZodTypeAny, {
//       [x: number]: string;
//       length: number;
//       toString: () => string;
//       toLocaleString: {
//           (): string;
//           (locales: string | string[], options?: Intl.NumberFormatOptions & 
// ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working drizzle/zod
Projects
None yet
Development

No branches or pull requests

3 participants