I have two problems with the following code.
interface MyForm {
age: number;
email: string;
name: string;
}
function Form<
T,
ComponentProps extends {
name: string;
onChange: (event: React.ChangeEvent) => void;
}
>(
props: {
component:
| React.ComponentClass<ComponentProps>
| React.ComponentType<ComponentProps>;
name: keyof T;
} & Omit<ComponentProps, "name" | "onChange">
) {
const { component: Component, name, ...rest } = props;
const handleChange = () => {
//
};
return <Component {...(rest as any)} name={name} onChange={handleChange} />;
}
function Component(props: {
name: string;
onChange: (event: React.ChangeEvent) => void;
color: "blue" | "yellow";
}) {
const { color, name, onChange } = props;
return <input name={name} onChange={onChange} style={{color}} />;
}
function App() {
return (
<>
{/* in this code, the name is not checked */}
<Form color="blue" component={Component} name="something" />
{/* in this code, the name is checked, but I must define all generics */}
<Form<MyForm, React.ComponentProps<typeof Component>>
color="yellow"
component={Component}
name="name"
/>
{/* this doesn't work */}
<Form<MyForm> color="blue" component={Component} name="email" />
</>
);
}
At first, I would like to call the Form component like this <Form<MyForm> color="blue" component={Component} name="email" /> instead of defining the second generic. In a complex component I have more properties and more generics and I don't want to enforce other programmers to define all generic only because I want that the name must match the keys in MyForm. And that's the goal, that the name must be checked by TypeScript and must be keyof MyForm. I know I can use optional generic and define the default type, but it breaks the logic and then I cannot pass color when calling Form. And I cannot define that the color is required, because the logic is, that the component must have name and onChange property and I don't care about the rest and just pass the rest to the component.
At second, I cannot get rid of the any in {...(rest as any)}. I don't know, why I am getting an error when I use only {...rest}.