React TypeScript 和 ForwardRef - 属性 'ref' 在类型 'IntrinsicAttributes 上不存在

React TypeScript & ForwardRef - Property 'ref' does not exist on type 'IntrinsicAttributes

在与 React 和 TypeScript 中的类型和 forwardRefs 斗争了很长一段时间后,我希望其他人可以为我解决这个问题。

我正在构建一个由三部分组成的 DataList 组件:

最终,用法将如下所示:

<DataList.List ...>
  <DataList.Item ...>content</DataList.Item>
</DataList.List>

为了实现我需要的功能,我正在利用 React.forwardRef,但我发现使用 TypeScript 很难做到这一点,因为我很难正确输入组件以接收 ref 以及 children 和其他道具。

DataListContainer
我基本上希望该组件在返回主要 DataList 组件(如下所示)时仅处理逻辑和事件侦听器。但这里的关键是我需要在这里创建 DataList ref 并将其分配给返回的组件。

const DataListContainer: React.FC = ({ children }) => {
  const listRef = useRef<HTMLUListElement>(null);

  return (
      <DataList ref={listRef}>{children}</DataList>
  );
};

数据列表
我希望 DataList 组件只处理它的 UI 和 props.

interface Props extends TestId {
  focusedItemId?: string;
}

const DataList: React.FC<Props> = React.forwardRef<HTMLUListElement, Props>(
  ({ children, focusedItemId, testId }, ref) => {
    return (
      <ul
        aria-activedescendant={focusedItemId}
        data-test-id={testId}
        ref={ref}
      >
        {children}
      </ul>
    );
  },
);

不过,这不太正确。因为这个设置给我错误

Type '{ children: any[]; ref: RefObject<HTMLUListElement>; }' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Property 'ref' does not exist on type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.

你快到了!在 React TypeScript Cheatsheet 之后,问题出在 DataList 道具上。添加 children 道具将修复它

interface Props extends TestId {
  children?: ReactNode;
  focusedItemId?: string;
}

我在 this CodeSandbox

中重新创建了一个简单示例