fabian-hiller / valibot

The modular and type safe schema library for validating structural data 🤖
https://valibot.dev
MIT License
5.67k stars 170 forks source link

Type instantiation is excessively deep and possively Infinite #590

Closed CestDiego closed 1 month ago

CestDiego commented 1 month ago

image

Hi I'm experiencing an issue that might or might not be my fault, but regardless I wanted to check in if I went a bit overboard with it. My code is below. I'm using drizzle-valibot to transform a drizzle schema into a RowSchema https://orm.drizzle.team/docs/valibot

I then extend that Schema to create a SpaceSchema that I will use when defining my GraphQL Types for and validate the input and output of my resolvers.

Up to that point, it's all good. The problem comes when I want to extend the NewSpaceSchema types and I find that it's not possible to infer types one more time because I get this error with no other error message. Luckily, this code is self contained and the steps to reproduce are to create a drizzle database schema, use drizzle-valibot to create the valibot schemas, extend those with a merge to have a entity schema (i.e. space) and extend that one more time to have a newEntity schema. And this works every time.

Plz Halp

import { createInsertSchema, createSelectSchema } from "drizzle-valibot";
import { brand, partial } from "valibot";

import {
  SpacesTable,
} from "./schema";
export const SelectSpacesRowSchema = brand(
  createSelectSchema(SpacesTable),
  "SelectSpacesRow",
);

export const SpaceSchema = brand(
  merge([
    SelectSpacesRowSchema,
    object({
      id: IdSchema,
      userProfileId: IdSchema,
      parentId: nullish(IdSchema),
      status: SpaceStatusSchema,
    }),
  ]),
  "Space",
);
export type SpaceSchema = Input<typeof SpaceSchema>;
export type Space = Output<typeof SpaceSchema>;

// Schema for new space
export const NewSpaceSchema = merge([
  required(omit(SpaceSchema, ["id", "createdAt", "updatedAt"])),
  object({
    // Images are needed so we can attach them to the correct place
    images: array(string()),
  }),
]);
export type NewSpaceSchema = Input<typeof NewSpaceSchema>;
export type NewSpace = Output<typeof NewSpaceSchema>;
fabian-hiller commented 1 month ago

What version of Valibot are you using? Please try changing your code by removing merge and let me know if it helps. The same goes for the other uses of merge.

// From this
const SpaceSchema = brand(
  merge([
    SelectSpacesRowSchema,
    object({
      id: IdSchema,
      userProfileId: IdSchema,
      parentId: nullish(IdSchema),
      status: SpaceStatusSchema,
    }),
  ]),
  "Space",
);

// To this
const SpaceSchema = brand(
  object({
    ..SelectSpacesRowSchema.entries,
    id: IdSchema,
    userProfileId: IdSchema,
    parentId: nullish(IdSchema),
    status: SpaceStatusSchema,
  }),
  "Space",
);

The general idea is explained here:

const ObjectSchema1 = v.object({ foo: v.string() });
const ObjectSchema2 = v.object({ bar: v.number() });

// Change this
const MergedObject = v.merge([ObjectSchema1, ObjectSchema2]);

// To this
const MergedObject = v.object({
  ...ObjectSchema1.entries,
  ...ObjectSchema2.entries,
});
CestDiego commented 1 month ago

Ohhh.... I can't use v0.30 yet :'( I'm stuck until drizzle-valibot supports it. Is there another way I could solve this with 0.29? Can't seem to find docs for the previous version. I love how the new version operates on the merges though :)

https://github.com/drizzle-team/drizzle-orm/issues/2358

fabian-hiller commented 1 month ago

You can already use the workaround in the older versions

fabian-hiller commented 1 month ago

I will close this issue for now, but feel free to ping me if you are still having problems.