vantezzen / auto-form

🌟 A React component that automatically creates a @shadcn/ui form based on a zod schema.
https://vantezzen.github.io/auto-form/
2.29k stars 81 forks source link

fieldConfig type safety for nested fields (z.object) #27

Open elliason opened 10 months ago

elliason commented 10 months ago

Hi, I have been doing some experiments with this form and have come across this problem: When I use only 1 level of fields, without any z.object in my schema, the autocomplete and type validation for fieldConfig works fine, but when I use some nested fields and objects in my schema, the autocompletion is lost. Consider this schema: `z.object({ group1: z.object({ username: z.string({ required_error: 'Username is required.', }),

    password: z.string({
        required_error: 'Password is required.',
    }),
}),

});` If I now try to put set some irrelevant property to fieldConfig, there is no warning: image

The expected behavior would be to throw a type error, as in the flat schema case: image

Is it because typescript is not able to correctly resolve the recursion type to FieldConfigItem ?

Also, I was wondering what approach you would recommend for extending the configuration options for the objects. I would like to be able to choose from more rendering components than just Accordion, but am not sure what is the best path to take. The best solution would be something type-safe.

Anyway, thanks for this great idea of schema based form !

vantezzen commented 10 months ago

I've also noticed this problem while creating the examples. In the type declarations, nested objects should be typed too but it looks like the declaration is wrong somewhere.

https://github.com/vantezzen/auto-form/blob/e02d0de88b19a2edb60cfac2e27b72e15739eb5a/src/components/ui/auto-form.tsx#L205-L210

As for extending, general props can be added to "AutoFormInputComponentProps" while new component types can be added to the "INPUT_COMPONENTS" object

https://github.com/vantezzen/auto-form/blob/e02d0de88b19a2edb60cfac2e27b72e15739eb5a/src/components/ui/auto-form.tsx#L463

paradisi-davide-servizi commented 7 months ago

Hey @vantezzen! amazing library so far, found a workaround by inspecting the zod type shape instead of the inferred type, it look something like this:

export type FieldConfig<SchemaType extends z.AnyZodObject> = {
  // If SchemaType.key is an object, create a nested FieldConfig, otherwise FieldConfigItem
  [Key in keyof SchemaType["shape"]]?: SchemaType["shape"][Key] extends z.AnyZodObject ?
  FieldConfig<SchemaType["shape"][Key]> :
  FieldConfigItem;
};