iway1 / react-ts-form

https://react-ts-form.com
MIT License
2.01k stars 35 forks source link

issue: Typesafe props don't work when combining refine(), transform() and createUniqueFieldSchema() #36

Closed DanielBreiner closed 1 year ago

DanielBreiner commented 1 year ago

Version Number

1.0.10

function Select({ options }: { options: string[] }) {
// ...
}

export const SelectStringSchema = createUniqueFieldSchema(z.string(), "select");

const mapping = [
    [z.string(), TextInput],
    [z.number(), NumberInput],
    [z.boolean(), Checkbox],
    [SelectStringSchema, Select] as const,
] as const;

In this very simple example, we the Form component doesn't expect the options props from Select - there's no error when we don't pass it and we get an error if we do try to pass it.

kiikoh commented 1 year ago

Ok I think this is the same problem I am running into. I wish I found this sooner, probably spent the last hours hunting this down.

iway1 commented 1 year ago

Hey thanks for the bug report - I'm actually not able to reproduce this issue. This worked for me:

import React from "react";
import { z } from "zod";
import { createUniqueFieldSchema } from "./createFieldSchema";
import { createTsForm } from "./createSchemaForm";

function Select({ options }: { options: string[] }) {
  return <div />;
}

function TextInput() {
  return <div />;
}
function NumberInput() {
  return <div />;
}
function Checkbox() {
  return <div />;
}

const SelectStringSchema = createUniqueFieldSchema(z.string(), "select");

const mapping = [
  [z.string(), TextInput],
  [z.number(), NumberInput],
  [z.boolean(), Checkbox],
  [SelectStringSchema, Select] as const,
] as const;

const Form = createTsForm(mapping);

export function Page() {
  return (
    <Form
      schema={z.object({
        t: z.string(),
        num: z.number(),
        select: SelectStringSchema,
      })}
      props={{
        select: {
          options: ["optionOne", "optionTwo"],
        },
      }}
      onSubmit={() => {}}
    />
  );
}

Would you mind sending the schema used for the form so I can investigate this further?

DanielBreiner commented 1 year ago

Alright, I was a bit confused at first - your code does indeed work correctly. In the end I found the issue: the props no longer work when a refine() and a transform() are applied to the schema. Not sure about the exact details, both refine() and transform() seem to work by themselves. Renaming the issue. Also posting the erroneous code:

import { createTsForm, createUniqueFieldSchema } from "@ts-react/form";
import React from "react";
import { z } from "zod";

function Select({ options }: { options: string[] }) {
  return <div />;
}

function TextInput() {
  return <div />;
}
function NumberInput() {
  return <div />;
}
function Checkbox() {
  return <div />;
}

const SelectStringSchema = createUniqueFieldSchema(z.string(), "select");

const mapping = [
  [z.string(), TextInput],
  [z.number(), NumberInput],
  [z.boolean(), Checkbox],
  [SelectStringSchema, Select] as const,
] as const;

const Form = createTsForm(mapping);

export function Page() {
  return (
    <Form
      schema={z
        .object({
          t: z.string(),
          num: z.number(),
          select: SelectStringSchema,
        })
        .refine((_) => true)
        .transform((a) => a)}
      props={{
        select: {
          options: ["optionOne", "optionTwo"],
        },
      }}
      onSubmit={() => {}}
    />
  );
}
iway1 commented 1 year ago

Actually it turns out the typing for createUniqueFieldSchema were indeed broken, I've got a fix for that but going to look into your issue with refine and transform as well before I create a new release. Thanks for the reproduction

DanielBreiner commented 1 year ago

Awesome. Thank you for the great work.