如何在单独的SELECT组件中键入ForwardRef?

我使用的技术是Reaction、TypeScrip和Style-Components。 我正在尝试创建选择组件,以便在Reaction Hook表单中使用它。 起初,看起来一切都是正确的,但我从打字脚本中得到了一个错误:

没有重载与此调用匹配。 重载第1个,共2个,‘(道具:Pick<;Pick<;Pick<;DetailedHTMLProps<;SelectHTMLAttributes,HTMLSelectElement&>,&t;Form&...262更多...|&t;在过渡结束捕获&;&;{...;}&;ISelectProps,&t;Form&q;更多...|...264更多...|&q;选项&>&;部分&>|...264更多...|";Options";&;{...;}&;{...;}):ReactElement<;...>;‘,出现以下错误。 类型‘ForwardedRef’不可赋值给类型‘RefObject|(RefObject&;((实例:HTMLSelectElement|NULL)=>;void))|(实例:HTMLSelectElement|NULL)=>;void)&;RefObject<;...>;)|(实例:HTMLSelectElement|NULL)=>;void)&;((实例:HTMLSelectElement|NULL)=>;void))|NULL|未定义’。 无法将类型‘MuableRefObject’赋给类型‘RefObject|(RefObject&;((实例:HTMLSelectElement|NULL)=>;void))|(实例:HTMLSelectElement|NULL)=>;void)&;RefObject<;...>;)|(实例:HTMLSelectElement|NULL)=>;void)&;((实例:HTMLSelectElement|NULL)=>;))|NULL|未定义’。 不能将类型‘MuableRefObject’赋给类型‘((实例:HTMLSelectElement|NULL)=>;void)&;RefObject’。 无法将类型‘MuableRefObject’赋值给类型‘(实例:HTMLSelectElement|NULL)=>;void’。 类型‘MuableRefObject’不提供与签名‘(实例:HTMLSelectElement|NULL):void’匹配的内容。

以下是我的代码:

import React, { forwardRef } from "react";
import styled from "styled-components";
import arrow from "../assets/svg/select_arrow.svg";

interface ISelectProps {
  options?: { name: string; value: string | number }[];
  name: string;
  ref?:
    | ((instance: HTMLSelectElement | null) => void)
    | React.RefObject<HTMLSelectElement>
    | null
    | undefined;
}

const SelectContainer = styled.div`
  display: flex;
  align-items: center;
  width: 100%;
  position: relative;
`;

const StyledSelect = styled.select<ISelectProps>`
  width: 100%;
  height: 30px;
  padding: 0 10px;
  background: ${({ theme }) => theme.colors.transparentButton};
  color: white;
  border: 1px solid white;
  border-radius: ${({ theme }) => theme.borderRadius};
  font-size: 14px;
  -moz-appearance: none; /* Firefox */
  -webkit-appearance: none; /* Safari and Chrome */
  appearance: none;
  &:focus,
  &:active {
    outline: none;
  }
`;

const StyledArrow = styled.img`
  position: absolute;
  right: 10px;
  padding: inherit;
`;

const Select = forwardRef(({ options, name }: ISelectProps, ref) => {
  return (
    <>
      <SelectContainer>
        <StyledSelect name={name} ref={ref}>
          {options?.map((op) => (
            <option value={op.value}>{op.name}</option>
          ))}
        </StyledSelect>
        <StyledArrow src={arrow} />
      </SelectContainer>
    </>
  );
});

export default Select;

codesandbox.io/s/eager-hertz-opbsi?file=/src/select.tsx

我做错了什么? 提前感谢所有有用的答案!


解决方案

首先,ref在这种情况下不是道具的一部分。 您应该为forwardRef提供两个泛型参数以帮助TS缩小类型范围。

什么是ref?它只是一个HTML元素

import React, { forwardRef } from "react";
import styled from "styled-components";

interface ISelectProps {
  options?: { name: string; value: string | number }[];
  name: string;

}

const SelectContainer = styled.div`
  display: flex;
  align-items: center;
  width: 100%;
  position: relative;
`;

const StyledSelect = styled.select<ISelectProps>`
  width: 100%;
  height: 30px;
  padding: 0 10px;
  background: ${({ theme }) => theme.colors.transparentButton};
  color: white;
  border: 1px solid white;
  border-radius: ${({ theme }) => theme.borderRadius};
  font-size: 14px;
  -moz-appearance: none; /* Firefox */
  -webkit-appearance: none; /* Safari and Chrome */
  appearance: none;
  &:focus,
  &:active {
    outline: none;
  }
`;

const StyledArrow = styled.img`
  position: absolute;
  right: 10px;
  padding: inherit;
`;

const Select = forwardRef<HTMLSelectElement, ISelectProps>(({ options, name }, ref) => {
  return (
    <>
      <SelectContainer>
        <StyledSelect name={name} ref={ref}>
          {options?.map((op) => (
            <option value={op.value}>{op.name}</option>
          ))}
        </StyledSelect>
      </SelectContainer>
    </>
  );
});

export default Select;

Playground link

相关文章