Restrict type usage for custom component in TypeScript #8557
-
Hi everyone! So, I would like to create a custom field component, for example, let's say that I want a I also followed the documentation for transforming and parsing string value to number: import TextField from '@mui/material/TextField';
import type { FieldValues, FieldPath, UseControllerProps } from 'react-hook-form';
import { useController } from 'react-hook-form';
export type NumberFieldProps<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = UseControllerProps<TFieldValues, TName>;
export const NumberField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>(props: NumberFieldProps<TFieldValues, TName>) => {
const { field, fieldState } = useController(props);
return (
<TextField
type="number"
inputProps={{ inputMode: 'decimal' }}
inputRef={field.ref}
name={field.name}
onBlur={field.onBlur}
onChange={(e) => {
const output = parseInt(e.target.value, 10);
field.onChange(isNaN(output) ? 0 : output);
}}
value={isNaN(field.value) || field.value === 0 ? '' : field.value.toString()}
{...(fieldState.error && { error: true, helperText: fieldState.error.message })}
/>
);
} My question is: For example: import type { SubmitHandler } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import { NumberField } from '~/components';
interface FormData {
num: number;
}
const FormContainer = () => {
const { control, handleSubmit } = useForm<FormData>({
defaultValues: {
num: 0,
},
});
const onSubmit: SubmitHandler<FormData> = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<NumberField
name="num"
control={control}
/>
</form>
);
}; No problem here. But if I set import type { SubmitHandler } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import { NumberField } from '~/components';
interface FormData {
num: string;
}
const FormContainer = () => {
const { control, handleSubmit } = useForm<FormData>({
defaultValues: {
num: '0',
},
});
const onSubmit: SubmitHandler<FormData> = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<NumberField
name="num" // I want TypeScript to throw error here because num is type of string and not type of number.
control={control}
/>
</form>
);
}; So, I don't know how to type my component interface correctly in order to restrict the usage to number type only. Thanks you ! EDIT: |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
I've opened a pull request that creates a type for using like this. check #8837. On the description it's also an example of usage: import {
FieldPathByValue,
FieldValues,
Control,
useController,
useForm
} from "react-hook-form";
// this component uses a date value
function SomeCustomFormComponent<
TFieldValues extends FieldValues,
TPath extends FieldPathByValue<TFieldValues, Date>
>({
control,
name
}: {
control: Control<TFieldValues>,
name: TPath
}) {
const { field } = useController({
control,
name,
});
// rest of components rules
}
function ExampleOfUsage () {
const {control} = useForm<{
foo: Date;
baz: string;
bar: {
baz: Date;
}
}>()
return (
<>
<SomeCustomFormComponent control={control} name="foo" /> {/* throw no error */}
<SomeCustomFormComponent control={control} name="baz" /> {/* throw an error since baz is string */}
<SomeCustomFormComponent control={control} name="bar.baz" /> {/* throw no error */}
</>
);
} |
Beta Was this translation helpful? Give feedback.
I've opened a pull request that creates a type for using like this. check #8837. On the description it's also an example of usage: