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

zodToConvexFields doesn't return the correct type when using zod transforms #70

Open
ericdew opened this issue Mar 1, 2024 · 1 comment

Comments

@ericdew
Copy link

ericdew commented Mar 1, 2024

When creating table fields using zod, using a transform on a zod schema results in:

  1. The return value of the transform is not used as the schema return type - instead the input type is always used
  2. Intellisense/autocomplete breaks when trying to get schema fields from the getEntDefinitions helper

Example implementation/use case:

import { defineEnt, defineEntSchema, getEntDefinitions } from "convex-ents";
import { zodToConvexFields } from "convex-helpers/server/zod";
import { z } from "zod";

const message = {
  sentTimestamp: z.string().transform((val) => new Date(val).getTime()),
  // ^ sentTimestamp: v.string()
  // expected: v.number()
};

const schema = defineEntSchema({
  messages: defineEnt(zodToConvexFields(message)),
});

const definitions = getEntDefinitions(schema);

type SentTimestamp = typeof definitions.messages.document.sentTimestamp;
// ^ "Value" / no type
// expected: number
// also no intellisense/autocomplete after typing "document."

// Zod is able so succesfully return the correct type for a string input transformed into a number
const result = z.object(message).parse({ sentTimestamp: "2024-01-01T00:00:00Z" });
type SentTimestamp = typeof result.sentTimestamp;
// ^ number (expected)
@ianmacartney
Copy link
Collaborator

Related to #69 the zodToConvexFields is intended to turn user input into values. It doesn't yet support generating validators for the output type, as you may want for your table.
I have a branch (zod) where I offer a second parameter to zodToConvexFields as "output" or "input" but I haven't figured out how to keep TypeScript from giving up on the recursive types.
I believe this may be the issue with (2) as well - running into the TypeScript inference capability, though I haven't debugged it.
I would suggest duplicating the table definition from the zod input validators. Until there's a zod library to wrap database reads & writes to transform values, it's a bit unclear what the guarantees are when using zod validators in this way, since zodToConvexFields just reduces to bare v.string() etc and doesn't run the zod code at all at runtime for db read/write.
See here for more details.
If you really want to share configs for frontend validation and db types, I would suggest manually overriding that types that have transforms / defaults:

const messageTableFields = {
  ...zodToConvexFields(message),
  sentTimestamp: v.number()
};

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

No branches or pull requests

2 participants