React Hook Form监听字段数组单个字段触发TypeScript错误
React Hook Form监听字段数组单个字段的TypeScript错误解决方法
问题场景
在React Hook Form中使用包含selected复选框字段的incomes字段数组,希望单独监听每个数组项的selected字段,但直接使用动态路径incomes[${index}].selected作为useWatch的name参数时,触发TypeScript错误:
No overload matches this call.
现有代码示例
Period组件(初始版本,监听整个数组)
const Period = ({ item, index, datepicker }) => { const { control } = useFormContext<InntektFormValues>(); const value = useWatch({ control, name: "incomes", }); return value[index].selected ? datepicker : <div className="min-w-[160px]"></div>; };
IncomeTable组件(渲染字段数组)
export const IncomeTable = () => { const { control } = useFormContext<IncomeFormValues>(); const incomeField = useFieldArray({ control, name: "incomes", }); return ( <> {incomeField.fields.map((item, index) => ( <TableRowWrapper key={item.id} cells={[ <Period item={item} index={index} datepicker={ <FormControlledDatePicker key={`incomes[${index}].from`} name={`incomes[${index}].from`} label="From" placeholder="DD.MM.ÅÅÅÅ" defaultValue={item?.from ?? null} hideLabel /> } />, ]} /> ))} </> ); };
尝试修改后的Period组件(触发TS错误)
const Period = ({ item, index, datepicker }) => { const { control } = useFormContext<InntektFormValues>(); const value = useWatch({ control, name: `incomes[${index}].selected`, // 此处触发TypeScript错误 }); };
错误原因
TypeScript对React Hook Form的字段路径进行严格的类型校验,动态拼接的字符串路径incomes[${index}].selected无法被TS静态推断为符合InntektFormValues结构的合法字段路径(FieldPath<InntektFormValues>类型),因此抛出类型不匹配的错误。
解决方法
方法1:使用FieldPath类型断言
通过类型断言明确告诉TS,动态生成的路径是合法的字段路径:
import { FieldPath, useWatch } from 'react-hook-form'; const Period = ({ item, index, datepicker }) => { const { control } = useFormContext<InntektFormValues>(); const selected = useWatch({ control, name: `incomes[${index}].selected` as FieldPath<InntektFormValues>, }); return selected ? datepicker : <div className="min-w-[160px]"></div>; };
方法2:使用useController替代useWatch
useController对动态字段路径的类型支持更友好,同时能直接获取字段的value:
import { useController } from 'react-hook-form'; const Period = ({ item, index, datepicker }) => { const { control } = useFormContext<InntektFormValues>(); const { field } = useController({ control, name: `incomes[${index}].selected` as FieldPath<InntektFormValues>, }); return field.value ? datepicker : <div className="min-w-[160px]"></div>; };
补充说明
如果你的InntektFormValues类型定义正确,确保incomes是数组类型且每个项包含selected字段,上述方法即可解决类型错误。类型断言是安全的,因为你明确知道动态路径符合表单结构。
内容的提问来源于stack exchange,提问作者Leff
相关产品推荐
相关产品推荐

