Skip to content

Instantly share code, notes, and snippets.

@vViktorPL
Last active November 5, 2020 12:20
Show Gist options
  • Save vViktorPL/ba54944594aa2fda75b8f3e877270417 to your computer and use it in GitHub Desktop.
Save vViktorPL/ba54944594aa2fda75b8f3e877270417 to your computer and use it in GitHub Desktop.
Advanced TypeScript - form
import * as React from 'react';
import { Controller, useForm, UseFormMethods } from 'react-hook-form'
import { Form, Input, InputNumber } from 'antd'
import { InputProps } from 'antd/es/input'
export type FormInputProps<FormValues, AsProps, Name> = {
name: Name;
form: UseFormMethods<FormValues>;
as: React.JSXElementConstructor<AsProps>;
} & Omit<AsProps, "form">;
export function FormInput<
FormValues extends Record<string, any>,
AsProps extends { defaultValue: FormValues[Name] },
Name extends keyof FormValues & string,
>({ name, form, as, ...rest }: FormInputProps<FormValues, AsProps, Name>) {
const { errors } = form;
return (
<Form.Item validateStatus={errors[name] && "error"} help={errors[name]}>
<Controller name={name} as={as} control={form.control as any} {...rest} />
</Form.Item>
);
}
type RegistrationForm = {
firstName: string;
lastName: string;
age: number;
}
export const TextInput = (props: InputProps & { defaultValue: string }) => <Input {...props} type="text" />;
const Test = () => {
const form = useForm<RegistrationForm>();
return (
<div>
<FormInput name="firstName" form={form} as={TextInput} size="large" defaultValue="" />
<FormInput name="lastName" form={form} as={TextInput} defaultValue="" />
<FormInput name="age" form={form} as={InputNumber} defaultValue={0} />
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment