T
TanStack11mo ago
vicious-gold

TypeScript types when creating your own UI components

So I have been trying to create some reusable UI components for a form similar to how the shadcn/ui form that is built on top of react-hook-form works. My attempt got added as an attachement but here are som snippets of the two components hardest to make work with TypeScript. Form:
type FormContextValue<TFormData = any> = FormApi<TFormData, ZodValidator>;

const FormContext = React.createContext<FormContextValue>(
{} as FormContextValue,
);

interface FormProps<TFormData> extends React.HTMLAttributes<HTMLFormElement> {
form: FormContextValue<TFormData>;
}

const Form = <TFormData,>({ form, ...props }: FormProps<TFormData>) => {
return (
<FormContext.Provider value={form}>
<form
onSubmit={async (e) => {
e.preventDefault();
e.stopPropagation();
await form.handleSubmit();
}}
{...props}
/>
</FormContext.Provider>
);
};
type FormContextValue<TFormData = any> = FormApi<TFormData, ZodValidator>;

const FormContext = React.createContext<FormContextValue>(
{} as FormContextValue,
);

interface FormProps<TFormData> extends React.HTMLAttributes<HTMLFormElement> {
form: FormContextValue<TFormData>;
}

const Form = <TFormData,>({ form, ...props }: FormProps<TFormData>) => {
return (
<FormContext.Provider value={form}>
<form
onSubmit={async (e) => {
e.preventDefault();
e.stopPropagation();
await form.handleSubmit();
}}
{...props}
/>
</FormContext.Provider>
);
};
And FormField:
type FormFieldContextValue = {
name: string;
};

const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue,
);

const FormField = <TFormData,>({
name,
children,
...props
}: FieldComponent<TFormData, ZodValidator> & {
children: (
fieldApi: FieldApi<unknown, string, undefined, undefined, unknown>,
) => React.ReactNode;
}) => {
const { Field } = React.useContext(FormContext);
return (
<FormFieldContext.Provider value={{ name }}>
<Field name={name} {...props}>
{children}
</Field>
</FormFieldContext.Provider>
);
};
type FormFieldContextValue = {
name: string;
};

const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue,
);

const FormField = <TFormData,>({
name,
children,
...props
}: FieldComponent<TFormData, ZodValidator> & {
children: (
fieldApi: FieldApi<unknown, string, undefined, undefined, unknown>,
) => React.ReactNode;
}) => {
const { Field } = React.useContext(FormContext);
return (
<FormFieldContext.Provider value={{ name }}>
<Field name={name} {...props}>
{children}
</Field>
</FormFieldContext.Provider>
);
};
I dont really know where to go or how to approach this further. I have been debugging for hours, but getting TypeScript to be friendly with this library when creating my own components has been a curse. I appreciate any feedback and help! With the current setup I am getting this error: 1. Type instantiation is excessively deep and possibly infinite. [2589]
0 Replies
No replies yetBe the first to reply to this messageJoin

Did you find this page helpful?