首页 > 解决方案 > 打字稿中这种复杂的“不可分配给类型”错误的解释

问题描述

我正在尝试将我的 React 项目迁移到 Typescript,但没有 Typescript 经验。我有一个组件,定义如下(精简):

interface InputProps {
  handleKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
  placeholder: string;
  style?: React.CSSProperties;
}
const Input: React.ForwardRefRenderFunction<HTMLInputElement, InputProps> = (
      ^^^^^
  { handleKeyDown, placeholder, style }: InputProps,
  ref: React.MutableRefObject<HTMLInputElement | null>
): JSX.Element => {
  return (
    <input
      ref={ref}
      onKeyDown={handleKeyDown}
      type="text"
      placeholder={placeholder}
      style={style}
    />
  );
};
export const ForwardedInput = React.forwardRef(Input);

现在我收到以下 TypeScript 错误const Input,这对我来说有点太复杂了,无法解开:

TS2322: Type '({ handleKeyDown, placeholder, style }: InputProps, ref: React.MutableRefObject<HTMLInputElement | null>) => JSX.Element' 
is not assignable to type 'ForwardRefRenderFunction<HTMLInputElement, InputProps>'.
  Types of parameters 'ref' and 'ref' are incompatible.
    Type 'MutableRefObject<HTMLInputElement | null> | ((instance: HTMLInputElement | null) => void) | null' is not assignable to type 'MutableRefObject<HTMLInputElement | null>'.
      Type 'null' is not assignable to type 'MutableRefObject<HTMLInputElement | null>'.

我猜我需要通过更改ref: React.MutableRefObject<HTMLInputElement | null>为其他东西来解决这个问题,但我不知道如何,因为我不知道错误的具体含义。

编辑:第一个答案建议使用泛型参数,所以我对函数进行了如下调整:

const Input = ({ handleKeyDown, placeholder, style }: InputProps, ref: any) => {

我必须键入 props 和 ref 以防止打字稿警告(我使用strict: "true"),实际上这消除了上述代码示例中的警告。

但是......使用任何导致:

ESLint: Unexpected any. Specify a different type.(@typescript-eslint/no-explicit-any)

据此,应该避免使用,应该使用,但是虽然消除了函数头中的警告,但它在输入组件上导致了一个很大的错误,说明与我的第一个错误相同的 ref 不兼容。TypeScript 比我想象的要难。anyunknownref={ref}

标签: reactjstypescript

解决方案


您可以使用泛型参数React.forwardRef

export const ForwardedInput = React.forwardRef<HTMLInputElement, InputProps>(
  (props, ref) => {
    const { handleKeyDown, placeholder, style } = props;
    return (
      <input
        ref={ref}
        onKeyDown={handleKeyDown}
        type="text"
        placeholder={placeholder}
        style={style}
      />
    );
  }
);

游乐场链接

如果您需要分离React.forwardRef调用及其功能,您可以使用React.ForwardRefRenderFunction泛型类型。

const ForwardInputRefFunction: React.ForwardRefRenderFunction<HTMLInputElement, InputProps> = (
  props,
  ref
) => {
  const { handleKeyDown, placeholder, style } = props;

  return (
    <input
      ref={ref}
      onKeyDown={handleKeyDown}
      type="text"
      placeholder={placeholder}
      style={style}
    />
  );
};

const ForwardedInput = React.forwardRef(ForwardInputRefFunction);

游乐场链接

您可以通过阅读node_modules. 要在代码沙箱中执行此操作,请使用Cmd + Left-click热键。


推荐阅读