You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:43:19