React-Hook-Form中useLens获取内部字段错误的TypeScript兼容方案
解决React-Hook-Form中Vector3D字段错误的TypeScript类型问题
针对你遇到的fieldState.error?["x"]触发TypeScript警告的问题,有以下几种可行的解决方式:
方式一:扩展FieldError类型适配Vector3D
定义一个继承自FieldError的自定义错误类型,明确包含Vector3D的x/y/z字段,然后在useController中指定该泛型,让TypeScript识别字段结构:
import { FieldError, useController } from "react-hook-form"; // 定义Vector3D对应的错误类型 type Vector3DError = FieldError & { x?: FieldError; y?: FieldError; z?: FieldError; }; function Vector3DComponent({ lens }: { lens: Lens<Vector3D> }) { // 指定useController的错误泛型为Vector3DError const { field, fieldState, formState } = useController<Vector3D, Vector3DError>(lens.interop()); return ( <Grid.Col span={4}> <Group gap="xs"> <SimpleGrid cols={4}> <input width={30} type="number" {...lens.focus("x").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> <input type="number" {...lens.focus("y").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> <input type="number" {...lens.focus("z").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> </SimpleGrid> {/* 现在可安全访问各字段错误 */} {fieldState.error?.x && <Text>{fieldState.error.x.message}</Text>} {fieldState.error?.y && <Text>{fieldState.error.y.message}</Text>} {fieldState.error?.z && <Text>{fieldState.error.z.message}</Text>} </Group> </Grid.Col> ); }
方式二:通过lens.focus单独获取字段错误状态
为每个x/y/z字段单独调用useController,直接获取对应字段的fieldState,这样类型会自动匹配,无需额外类型定义:
function Vector3DComponent({ lens }: { lens: Lens<Vector3D> }) { // 分别获取三个字段的状态 const { fieldState: xFieldState } = useController(lens.focus("x").interop()); const { fieldState: yFieldState } = useController(lens.focus("y").interop()); const { fieldState: zFieldState } = useController(lens.focus("z").interop()); return ( <Grid.Col span={4}> <Group gap="xs"> <SimpleGrid cols={4}> <input width={30} type="number" {...lens.focus("x").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> <input type="number" {...lens.focus("y").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> <input type="number" {...lens.focus("z").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> </SimpleGrid> {/* 直接使用各字段的错误状态 */} {xFieldState.error && <Text>{xFieldState.error.message}</Text>} {yFieldState.error && <Text>{yFieldState.error.message}</Text>} {zFieldState.error && <Text>{zFieldState.error.message}</Text>} </Group> </Grid.Col> ); }
方式三:类型断言(谨慎使用)
如果不想修改类型或多调用useController,可以用类型断言跳过TypeScript的检查,但这种方式会失去类型安全,仅在确定结构正确时使用:
function Vector3DComponent({ lens }: { lens: Lens<Vector3D> }) { const { field, fieldState, formState } = useController(lens.interop()); // 断言错误对象包含Vector3D的字段 const vectorError = fieldState.error as FieldError & Partial<Record<keyof Vector3D, FieldError>>; return ( <Grid.Col span={4}> <Group gap="xs"> <SimpleGrid cols={4}> <input width={30} type="number" {...lens.focus("x").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> <input type="number" {...lens.focus("y").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> <input type="number" {...lens.focus("z").interop((ctrl, name) => ctrl.register(name, { valueAsNumber: true }) )} /> </SimpleGrid> {vectorError?.x && <Text>{vectorError.x.message}</Text>} {vectorError?.y && <Text>{vectorError.y.message}</Text>} {vectorError?.z && <Text>{vectorError.z.message}</Text>} </Group> </Grid.Col> ); }
内容的提问来源于stack exchange,提问作者Todilo
相关产品推荐
相关产品推荐

