reactjs - Hvordan gi fleksibel typetilordning for en tilpasset Input-komponent ved bruk av React Hook Form med TypeScript
Hvis jeg har en generell Input-komponent i en React Hook Form som kan brukes både for registrerings- og innloggingsskjemaer, hvordan kan jeg gjøre IFormValues fleksibel, slik at den kan brukes for begge skjemaene som har forskjellige inputfelt? Registrering har inputfelt for e-post, passord og bekreft passord, mens Innlogging kun har inputfelt for e-post og passord.
interface IFormValues {
email: string;
password: string;
confirmPassword: string;
}
type InputProps = {
hookValue: Path<IFormValues>;
register: UseFormRegister<IFormValues>;
id: string;
...etc
};
const Input = ({ hookValue, id, ...etc }: InputProps) =>
<StyledInput {...register(hookValue)} id={id} ...etc />
Ville det være en unionstype som dette? (eller er det en måte å sende inn den riktige typen som brukes til input-komponenten?)
interface ISignIn {
email: string;
password: string;
}
interface ISignUp extends ISignIn {
confirmPassword: string;
}
type InputProps = {
hookValue: Path<ISignIn | ISignUp>;
register: UseFormRegister<ISignIn | ISignUp>;
id: string;
...etc
};
Jeg prøvde å implementere med det ovenfor, men dette gir meg følgende TypeScript-feil når jeg kaller komponenten:
<Input
register={register} // this errors with the below output
hookValue="email"
label="Email"
/>
(property) register: UseFormRegister<ISignUp | ISignIn>
Type 'UseFormRegister<{ email: string; password: string; confirmPassword: string; }>' is not assignable to type 'UseFormRegister<ISignUp | ISignIn>'.
Type 'ISignUp | ISignIn' is not assignable to type '{ email: string; password: string; confirmPassword: string; }'.
Property 'confirmPassword' is missing in type 'ISignIn' but required in type '{ email: string; password: string; confirmPassword: string; }'.ts(2322)
input.component.tsx(24, 3): The expected type comes from property 'register' which is declared here on type 'IntrinsicAttributes & InputProps'
Svar #1
Jeg klarte å få dette til å fungere med følgende, ved å bruke extend som jeg forstår fungerer som en begrensning på generisk type - i praksis sikrer det at den kan tilordnes den typen, men beholder den strengere utledede verdien.
export type ISignIn = {
email: string;
password: string;
};
export type ISignUp = {
email: string;
password: string;
confirmPassword: string;
};
type InputProps<IFormValues extends ISignIn | ISignUp> = {
hookValue: Path<IFormValues>;
register: UseFormRegister<IFormValues>;
};
const Input = <IFormValues extends ISignIn | ISignUp>({
hookValue,
register,
}: InputProps<IFormValues>) => {
Svar #2
løsning 1: bruk &-operatoren som ISignIn & ISignUp
løsning 2: typeof-type-vakter
